Improve navigation

This commit is contained in:
TheXamlGuy
2024-05-16 22:30:01 +01:00
parent 7f3c4c53cc
commit 85a14a8259
9 changed files with 53 additions and 38 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ public class ContentControlHandler :
{ {
public async Task Handle(NavigateEventArgs<ContentControl> args) public async Task Handle(NavigateEventArgs<ContentControl> args)
{ {
if (args.Context is ContentControl contentControl) if (args.Region is ContentControl contentControl)
{ {
if (args.Template is Control control) if (args.Template is Control control)
{ {
+1 -1
View File
@@ -8,7 +8,7 @@ public class ContentDialogHandler(IDispatcher dispatcher) :
{ {
public async Task Handle(NavigateEventArgs<ContentDialog> args) public async Task Handle(NavigateEventArgs<ContentDialog> args)
{ {
if (args.Context is ContentDialog contentDialog) if (args.Region is ContentDialog contentDialog)
{ {
contentDialog.DataContext = args.Content; contentDialog.DataContext = args.Content;
+1 -1
View File
@@ -14,7 +14,7 @@ public class FrameHandler :
{ {
public Task Handle(NavigateEventArgs<Frame> args) public Task Handle(NavigateEventArgs<Frame> args)
{ {
if (args.Context is Frame frame) if (args.Region is Frame frame)
{ {
frame.NavigationPageFactory ??= new NavigationPageFactory(); frame.NavigationPageFactory ??= new NavigationPageFactory();
if (args.Template is Control control) if (args.Template is Control control)
+6 -3
View File
@@ -2,8 +2,11 @@
public interface INavigationScope public interface INavigationScope
{ {
void Navigate(string route, object? sender = null, object? context = null, void Navigate(string route,
EventHandler? navigated = null, object[]? parameters = null); object? sender = null,
object? region = null,
EventHandler? navigated = null,
object[]? parameters = null);
void Back(object? context); void Back(object? region);
} }
+2 -2
View File
@@ -1,13 +1,13 @@
namespace Toolkit.Foundation; namespace Toolkit.Foundation;
public record NavigateEventArgs(string Route, public record NavigateEventArgs(string Route,
object? Context = null, object? Region = null,
string? Scope = null, string? Scope = null,
object? Sender = null, object? Sender = null,
EventHandler? Navigated = null, EventHandler? Navigated = null,
object[]? Parameters = null); object[]? Parameters = null);
public record NavigateEventArgs<TNavigation>(object Context, public record NavigateEventArgs<TNavigation>(object Region,
object Template, object Template,
object Content, object Content,
object? Sender = null, object? Sender = null,
+1 -1
View File
@@ -20,7 +20,7 @@ public class NavigateHandler(NamedComponent scope,
} }
navigationScope?.Navigate(args.Route, args.Sender, navigationScope?.Navigate(args.Route, args.Sender,
args.Context, args.Navigated, args.Parameters); args.Region, args.Navigated, args.Parameters);
return Task.CompletedTask; return Task.CompletedTask;
} }
+24 -13
View File
@@ -1,4 +1,5 @@
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using System.Data.SqlTypes;
namespace Toolkit.Foundation; namespace Toolkit.Foundation;
@@ -6,16 +7,21 @@ public class NavigationScope(IPublisher publisher,
IServiceProvider provider, IServiceProvider provider,
IServiceFactory factory, IServiceFactory factory,
INavigationProvider navigationProvider, INavigationProvider navigationProvider,
INavigationRegionProvider navigationContextProvider, INavigationRegionProvider navigationRegionProvider,
IContentTemplateDescriptorProvider contentTemplateDescriptorProvider) : IContentTemplateDescriptorProvider contentTemplateDescriptorProvider) :
INavigationScope INavigationScope
{ {
public void Navigate(string route, public void Navigate(string route,
object? sender = null, object? sender = null,
object? context = null, object? region = null,
EventHandler? navigated = null, EventHandler? navigated = null,
object[]? parameters = null) object[]? parameters = null)
{ {
if (region is null)
{
return;
}
string[] segments = route.Split('/'); string[] segments = route.Split('/');
int segmentCount = segments.Length; int segmentCount = segments.Length;
int currentSegmentIndex = 0; int currentSegmentIndex = 0;
@@ -44,28 +50,33 @@ public class NavigationScope(IPublisher publisher,
if (provider.GetRequiredKeyedService(descriptor.TemplateType, segment) is object view) if (provider.GetRequiredKeyedService(descriptor.TemplateType, segment) is object view)
{ {
if (context is not null) if (region is not null)
{ {
if (navigationContextProvider.TryGet(context, out object? scopedContext)) switch (region)
{ {
context = scopedContext; case "self":
region = view;
break;
default:
if (navigationRegionProvider.TryGet(region, out object? value))
{
region = value;
}
break;
} }
} }
else
{
context = view;
}
if (context is not null) if (region is not null)
{ {
if ((parameters is { Length: > 0 } if ((parameters is { Length: > 0 }
? factory.Create(descriptor.ContentType, parameters) ? factory.Create(descriptor.ContentType, parameters)
: provider.GetRequiredKeyedService(descriptor.ContentType, segment)) is object viewModel) : provider.GetRequiredKeyedService(descriptor.ContentType, segment)) is object viewModel)
{ {
if (navigationProvider.Get(context is Type type ? type : context.GetType()) is INavigation navigation) if (navigationProvider.Get(region is Type type ? type : region.GetType()) is INavigation navigation)
{ {
Type navigateType = typeof(NavigateEventArgs<>).MakeGenericType(navigation.Type); Type navigateType = typeof(NavigateEventArgs<>).MakeGenericType(navigation.Type);
if (Activator.CreateInstance(navigateType, [context, view, viewModel, sender, parameters]) is object navigate) if (Activator.CreateInstance(navigateType, [region, view, viewModel, sender, parameters]) is object navigate)
{ {
publisher.Publish(navigate); publisher.Publish(navigate);
if (currentSegmentIndex == segmentCount) if (currentSegmentIndex == segmentCount)
@@ -85,7 +96,7 @@ public class NavigationScope(IPublisher publisher,
{ {
if (context is not null) if (context is not null)
{ {
navigationContextProvider.TryGet(context, out context); navigationRegionProvider.TryGet(context, out context);
} }
if (context is not null) if (context is not null)
+11 -10
View File
@@ -1,4 +1,5 @@
using Avalonia; using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Metadata; using Avalonia.Metadata;
using Avalonia.Xaml.Interactivity; using Avalonia.Xaml.Interactivity;
@@ -10,9 +11,6 @@ public class NavigateAction :
AvaloniaObject, AvaloniaObject,
IAction IAction
{ {
public static readonly StyledProperty<object> ContextProperty =
AvaloniaProperty.Register<NavigateAction, object>(nameof(Context));
public static readonly DirectProperty<NavigateAction, ParameterBindingCollection> ParameterBindingsProperty = public static readonly DirectProperty<NavigateAction, ParameterBindingCollection> ParameterBindingsProperty =
AvaloniaProperty.RegisterDirect<NavigateAction, ParameterBindingCollection>(nameof(ParameterBindings), AvaloniaProperty.RegisterDirect<NavigateAction, ParameterBindingCollection>(nameof(ParameterBindings),
x => x.ParameterBindings); x => x.ParameterBindings);
@@ -20,6 +18,9 @@ public class NavigateAction :
public static readonly StyledProperty<object[]?> ParametersProperty = public static readonly StyledProperty<object[]?> ParametersProperty =
AvaloniaProperty.Register<NavigateAction, object[]?>(nameof(Parameters)); AvaloniaProperty.Register<NavigateAction, object[]?>(nameof(Parameters));
public static readonly StyledProperty<object> RegionProperty =
AvaloniaProperty.Register<NavigateAction, object>(nameof(Region));
public static readonly StyledProperty<string> RouteProperty = public static readonly StyledProperty<string> RouteProperty =
AvaloniaProperty.Register<NavigateAction, string>(nameof(Route)); AvaloniaProperty.Register<NavigateAction, string>(nameof(Route));
@@ -30,10 +31,10 @@ public class NavigateAction :
public event EventHandler? Navigated; public event EventHandler? Navigated;
public object Context public object Region
{ {
get => GetValue(ContextProperty); get => GetValue(RegionProperty);
set => SetValue(ContextProperty, value); set => SetValue(RegionProperty, value);
} }
[Content] [Content]
@@ -61,12 +62,12 @@ public class NavigateAction :
public object Execute(object? sender, public object Execute(object? sender,
object? parameter) object? parameter)
{ {
if (sender is TemplatedControl control) if (sender is Control content)
{ {
Dictionary<string, object> arguments = Dictionary<string, object> arguments =
new(StringComparer.InvariantCultureIgnoreCase); new(StringComparer.InvariantCultureIgnoreCase);
if (control.DataContext is IObservableViewModel observableViewModel) if (content.DataContext is IObservableViewModel observableViewModel)
{ {
object[] parameters = [.. Parameters ?? Enumerable.Empty<object?>(), object[] parameters = [.. Parameters ?? Enumerable.Empty<object?>(),
.. ..
@@ -74,8 +75,8 @@ public class NavigateAction :
ParameterBindings.Select(binding => new KeyValuePair<string, object>(binding.Key, binding.Value)).ToArray() : ParameterBindings.Select(binding => new KeyValuePair<string, object>(binding.Key, binding.Value)).ToArray() :
Enumerable.Empty<KeyValuePair<string, object>>()]; Enumerable.Empty<KeyValuePair<string, object>>()];
observableViewModel.Publisher.Publish(new NavigateEventArgs(Route, Context == this ? control : Context, Scope ?? null, observableViewModel.Publisher.Publish(new NavigateEventArgs(Route, Region == this ? content : Region, Scope ?? null,
control.DataContext, Navigated, parameters)); content.DataContext, Navigated, parameters));
} }
} }
+6 -6
View File
@@ -9,16 +9,16 @@ public class NavigateBackAction :
AvaloniaObject, AvaloniaObject,
IAction IAction
{ {
public static readonly StyledProperty<string> ContextProperty = public static readonly StyledProperty<string> RegionProperty =
AvaloniaProperty.Register<NavigateBackAction, string>(nameof(Context)); AvaloniaProperty.Register<NavigateBackAction, string>(nameof(Region));
public static readonly StyledProperty<string> ScopeProperty = public static readonly StyledProperty<string> ScopeProperty =
AvaloniaProperty.Register<NavigateBackAction, string>(nameof(Scope)); AvaloniaProperty.Register<NavigateBackAction, string>(nameof(Scope));
public string Context public string Region
{ {
get => GetValue(ContextProperty); get => GetValue(RegionProperty);
set => SetValue(ContextProperty, value); set => SetValue(RegionProperty, value);
} }
public string Scope public string Scope
@@ -34,7 +34,7 @@ public class NavigateBackAction :
{ {
if (control.DataContext is IObservableViewModel observableViewModel) if (control.DataContext is IObservableViewModel observableViewModel)
{ {
observableViewModel.Publisher.Publish(new NavigateBackEventArgs(Context observableViewModel.Publisher.Publish(new NavigateBackEventArgs(Region
?? null, Scope ?? null)); ?? null, Scope ?? null));
} }
} }