From 87372da4d884da954a8a28e4279820feb5f9838d Mon Sep 17 00:00:00 2001 From: Easley Date: Tue, 12 Nov 2024 11:06:18 +0800 Subject: [PATCH] https://github.com/NeverMorewd/Lemon.ModuleNavigation/issues/29 --- .../Regions/AvaloniauiRegion.cs | 22 ++++++++---- .../Regions/ContentRegion.cs | 2 +- .../ViewModels/MainViewModel.cs | 12 +++---- .../Abstracts/IViewNavigationService.cs | 4 +-- src/Lemon.ModuleNavigation/ConcurrentItem.cs | 36 +++++++++++++++++++ .../Core/NavigationContext.cs | 10 +++--- .../Core/NavigationService.cs | 6 ++-- .../Internals/ConcurrentSet.cs | 2 +- .../Internals/DisposableAction.cs | 2 +- .../Parameters/BaseParameters.cs | 8 ++--- 10 files changed, 73 insertions(+), 31 deletions(-) create mode 100644 src/Lemon.ModuleNavigation/ConcurrentItem.cs diff --git a/src/Lemon.ModuleNavigation.Avaloniaui/Regions/AvaloniauiRegion.cs b/src/Lemon.ModuleNavigation.Avaloniaui/Regions/AvaloniauiRegion.cs index c7e70f0..3f70c7e 100644 --- a/src/Lemon.ModuleNavigation.Avaloniaui/Regions/AvaloniauiRegion.cs +++ b/src/Lemon.ModuleNavigation.Avaloniaui/Regions/AvaloniauiRegion.cs @@ -10,9 +10,11 @@ namespace Lemon.ModuleNavigation.Avaloniaui.Regions public abstract class AvaloniauiRegion : IRegion { private readonly Dictionary _viewCache; + private readonly ConcurrentItem<(IView, INavigationAware)> _current; public AvaloniauiRegion() { _viewCache = []; + _current = new(); RegionTemplate = GetDataTemplate(); } public abstract string Name @@ -41,24 +43,30 @@ private IDataTemplate GetDataTemplate() { return default; } - if (context.RequestNew || !_viewCache.TryGetValue(context.ViewName, out IView? view)) + if (context.RequestNew || !_viewCache.TryGetValue(context.TargetViewName, out IView? view)) { - view = context.ServiceProvider.GetRequiredKeyedService(context.ViewName); + view = context.ServiceProvider.GetRequiredKeyedService(context.TargetViewName); var viewFullName = view.GetType().FullName; context.Uri = new Uri($"avares://{viewFullName}.axaml"); - var viewModel = context.ServiceProvider.GetRequiredKeyedService(context.ViewName); - viewModel.OnNavigatedTo(context); - if (viewModel.IsNavigationTarget(context)) + var navigationAware = context.ServiceProvider.GetRequiredKeyedService(context.TargetViewName); + if (_current.TryTakeData(out (IView, INavigationAware) data)) { - view.DataContext = viewModel; + data.Item2.OnNavigatedFrom(context); + } + if (navigationAware.IsNavigationTarget(context)) + { + view.DataContext = navigationAware; + navigationAware.OnNavigatedTo(context); + _current.SetData((view, navigationAware)); } else { return default; } - _viewCache.TryAdd(context.ViewName, view); + + _viewCache.TryAdd(context.TargetViewName, view); } return view as Control; }); diff --git a/src/Lemon.ModuleNavigation.Avaloniaui/Regions/ContentRegion.cs b/src/Lemon.ModuleNavigation.Avaloniaui/Regions/ContentRegion.cs index 81b9cce..18b5d50 100644 --- a/src/Lemon.ModuleNavigation.Avaloniaui/Regions/ContentRegion.cs +++ b/src/Lemon.ModuleNavigation.Avaloniaui/Regions/ContentRegion.cs @@ -38,7 +38,7 @@ public override void Activate(NavigationContext target) { if(Content is NavigationContext current) { - if (target.ViewName == current.ViewName) + if (target.TargetViewName == current.TargetViewName) { return; } diff --git a/src/Lemon.ModuleNavigation.Sample/ViewModels/MainViewModel.cs b/src/Lemon.ModuleNavigation.Sample/ViewModels/MainViewModel.cs index ef3bb63..e11013e 100644 --- a/src/Lemon.ModuleNavigation.Sample/ViewModels/MainViewModel.cs +++ b/src/Lemon.ModuleNavigation.Sample/ViewModels/MainViewModel.cs @@ -30,7 +30,7 @@ public MainViewModel(IEnumerable modules, _dialogService = dialogService; _regionManager = regionManager; // default view - _navigationService.NavigateToView("ContentRegion", "ViewAlpha", false); + _navigationService.RequestViewNavigation("ContentRegion", "ViewAlpha", false); Modules = new ObservableCollection(modules); ToViewCommand = ReactiveCommand.Create(content => { @@ -42,10 +42,10 @@ public MainViewModel(IEnumerable modules, requestNew = true; } - _navigationService.NavigateToView("ContentRegion", viewName, requestNew); - _navigationService.NavigateToView("TabRegion", viewName, requestNew); - _navigationService.NavigateToView("ItemsRegion", viewName, requestNew); - _navigationService.NavigateToView("TransitioningContentRegion", viewName, requestNew); + _navigationService.RequestViewNavigation("ContentRegion", viewName, requestNew); + _navigationService.RequestViewNavigation("TabRegion", viewName, requestNew); + _navigationService.RequestViewNavigation("ItemsRegion", viewName, requestNew); + _navigationService.RequestViewNavigation("TransitioningContentRegion", viewName, requestNew); }); ToDialogCommand = ReactiveCommand.Create(content => { @@ -78,7 +78,7 @@ public MainViewModel(IEnumerable modules, }); _regionManager.Subscribe(n => { - _logger.LogDebug($"Request to : {n.RegionName}.{n.ViewName}"); + _logger.LogDebug($"Request to : {n.RegionName}.{n.TargetViewName}"); }); _regionManager.Subscribe(r => { diff --git a/src/Lemon.ModuleNavigation/Abstracts/IViewNavigationService.cs b/src/Lemon.ModuleNavigation/Abstracts/IViewNavigationService.cs index 7fd6233..a89a579 100644 --- a/src/Lemon.ModuleNavigation/Abstracts/IViewNavigationService.cs +++ b/src/Lemon.ModuleNavigation/Abstracts/IViewNavigationService.cs @@ -5,10 +5,10 @@ namespace Lemon.ModuleNavigation.Abstracts public interface IViewNavigationService { IDisposable BindingViewNavigationHandler(IViewNavigationHandler handler); - void NavigateToView(string regionName, + void RequestViewNavigation(string regionName, string viewKey, bool requestNew = false); - void NavigateToView(string regionName, + void RequestViewNavigation(string regionName, string viewKey, NavigationParameters parameters, bool requestNew = false); diff --git a/src/Lemon.ModuleNavigation/ConcurrentItem.cs b/src/Lemon.ModuleNavigation/ConcurrentItem.cs new file mode 100644 index 0000000..31e280a --- /dev/null +++ b/src/Lemon.ModuleNavigation/ConcurrentItem.cs @@ -0,0 +1,36 @@ +using System.Collections.Concurrent; + +namespace Lemon.ModuleNavigation +{ + public class ConcurrentItem + { + private const int SIZE = 1; + private readonly BlockingCollection _collection = new(SIZE); + public ConcurrentItem() { } + + public void SetData(T data) + { + if (_collection.Count == SIZE) + { + _collection.Take(); + } + _collection.Add(data); + } + + public T TakeData() + { + return _collection.Take(); + } + + public bool TryTakeData(out T? data) + { + return _collection.TryTake(out data); + } + + public bool WaitForData(TimeSpan timeSpan, out T? data) + { + return _collection.TryTake(out data, timeSpan); + } + } + +} diff --git a/src/Lemon.ModuleNavigation/Core/NavigationContext.cs b/src/Lemon.ModuleNavigation/Core/NavigationContext.cs index 984388f..9e7674f 100644 --- a/src/Lemon.ModuleNavigation/Core/NavigationContext.cs +++ b/src/Lemon.ModuleNavigation/Core/NavigationContext.cs @@ -9,7 +9,7 @@ internal NavigationContext(string viewName, bool requestNew, NavigationParameters? navigationParameters) { - ViewName = viewName; + TargetViewName = viewName; Parameters = navigationParameters; RequestNew = requestNew; RegionName = regionName; @@ -18,7 +18,7 @@ internal NavigationContext(string viewName, } public static ViewNameComparer ViewNameComparer => new(); public static StrictComparer StrictComparer => new(); - public string ViewName + public string TargetViewName { get; private set; @@ -50,7 +50,7 @@ public IServiceProvider ServiceProvider } public override string ToString() { - return ViewName; + return TargetViewName; } } public class ViewNameComparer : IEqualityComparer @@ -59,12 +59,12 @@ public bool Equals(NavigationContext? x, NavigationContext? y) { if (x == null && y == null) return true; if (x == null || y == null) return false; - return x.ViewName == y.ViewName; + return x.TargetViewName == y.TargetViewName; } public int GetHashCode(NavigationContext obj) { - return obj.ViewName.GetHashCode(); + return obj.TargetViewName.GetHashCode(); } } public class StrictComparer : IEqualityComparer diff --git a/src/Lemon.ModuleNavigation/Core/NavigationService.cs b/src/Lemon.ModuleNavigation/Core/NavigationService.cs index 293ab48..b346f8c 100644 --- a/src/Lemon.ModuleNavigation/Core/NavigationService.cs +++ b/src/Lemon.ModuleNavigation/Core/NavigationService.cs @@ -8,6 +8,8 @@ public class NavigationService : INavigationService { private readonly List _handlers = []; private readonly List _viewHandlers = []; + + // reserve only one for now. private readonly ConcurrentStack<(IModule module, NavigationParameters parameter)> _bufferModule = []; private readonly ConcurrentStack<(string moduleName, NavigationParameters parameter)> _bufferModuleName = []; private readonly ConcurrentStack<(string regionName, string viewName, bool requestNew)> _bufferViewName = []; @@ -36,7 +38,7 @@ public void RequestModuleNavigate(string moduleName, NavigationParameters parame } _bufferModuleName.Push((moduleName, parameters)); } - public void NavigateToView(string regionName, + public void RequestViewNavigation(string regionName, string viewKey, bool requestNew = false) { @@ -86,7 +88,7 @@ IDisposable IViewNavigationService.BindingViewNavigationHandler(IViewNavigationH }); } - public void NavigateToView(string regionName, + public void RequestViewNavigation(string regionName, string viewKey, NavigationParameters parameters, bool requestNew = false) diff --git a/src/Lemon.ModuleNavigation/Internals/ConcurrentSet.cs b/src/Lemon.ModuleNavigation/Internals/ConcurrentSet.cs index 5df8ce3..896e9f8 100644 --- a/src/Lemon.ModuleNavigation/Internals/ConcurrentSet.cs +++ b/src/Lemon.ModuleNavigation/Internals/ConcurrentSet.cs @@ -3,7 +3,7 @@ namespace Lemon.ModuleNavigation.Internals { - internal class ConcurrentSet : IEnumerable where T : notnull + internal sealed class ConcurrentSet : IEnumerable where T : notnull { private readonly ConcurrentDictionary _dict = new(); diff --git a/src/Lemon.ModuleNavigation/Internals/DisposableAction.cs b/src/Lemon.ModuleNavigation/Internals/DisposableAction.cs index 3c4aaf2..7df8749 100644 --- a/src/Lemon.ModuleNavigation/Internals/DisposableAction.cs +++ b/src/Lemon.ModuleNavigation/Internals/DisposableAction.cs @@ -1,6 +1,6 @@ namespace Lemon.ModuleNavigation.Internals { - internal class DisposableAction : IDisposable + internal sealed class DisposableAction : IDisposable { private readonly Action _action; private int _disposed; diff --git a/src/Lemon.ModuleNavigation/Parameters/BaseParameters.cs b/src/Lemon.ModuleNavigation/Parameters/BaseParameters.cs index 8b2ebc1..db8b142 100644 --- a/src/Lemon.ModuleNavigation/Parameters/BaseParameters.cs +++ b/src/Lemon.ModuleNavigation/Parameters/BaseParameters.cs @@ -1,10 +1,6 @@ -using System; -using System.Collections; -using System.Collections.Generic; +using System.Collections; using System.ComponentModel; -using System.Linq; using System.Text; -using System.Threading.Tasks; namespace Lemon.ModuleNavigation.Parameters { @@ -55,7 +51,7 @@ public IEnumerable GetValues(string key) where T : notnull } public bool TryGetValue(string key, out T? value) where T : notnull { - return _entries.TryGetValue(key, out value); + return _entries.TryGetValue(key, out value); } IEnumerator IEnumerable.GetEnumerator() {