Parameter improvements
This commit is contained in:
@@ -42,18 +42,13 @@ public class ContentTemplate :
|
|||||||
|
|
||||||
async void HandleUnloaded(object? sender, RoutedEventArgs args)
|
async void HandleUnloaded(object? sender, RoutedEventArgs args)
|
||||||
{
|
{
|
||||||
control.Unloaded -= HandleLoaded;
|
control.Unloaded -= HandleUnloaded;
|
||||||
if (control.DataContext is object content)
|
if (control.DataContext is object content)
|
||||||
{
|
{
|
||||||
if (content is IDeactivated deactivated)
|
if (content is IDeactivated deactivated)
|
||||||
{
|
{
|
||||||
await deactivated.OnDeactivated();
|
await deactivated.OnDeactivated();
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (content is IDisposable disposable)
|
|
||||||
//{
|
|
||||||
// disposable.Dispose();
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Interactivity;
|
||||||
using FluentAvalonia.UI.Media.Animation;
|
using FluentAvalonia.UI.Media.Animation;
|
||||||
using FluentAvalonia.UI.Navigation;
|
using FluentAvalonia.UI.Navigation;
|
||||||
using Toolkit.Foundation;
|
using Toolkit.Foundation;
|
||||||
|
using Toolkit.UI.Avalonia;
|
||||||
using Toolkit.UI.Controls.Avalonia;
|
using Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
namespace Toolkit.Avalonia;
|
namespace Toolkit.Avalonia;
|
||||||
@@ -18,66 +19,57 @@ public class FrameHandler :
|
|||||||
frame.NavigationPageFactory ??= new NavigationPageFactory();
|
frame.NavigationPageFactory ??= new NavigationPageFactory();
|
||||||
if (args.Template is Control control)
|
if (args.Template is Control control)
|
||||||
{
|
{
|
||||||
void NavigatingFrom(Control sender)
|
|
||||||
{
|
|
||||||
async void HandleNavigatingFrom(object? _,
|
|
||||||
NavigatingCancelEventArgs args)
|
|
||||||
{
|
|
||||||
sender.RemoveHandler(Frame.NavigatingFromEvent, HandleNavigatingFrom);
|
|
||||||
NavigatedFrom(sender);
|
|
||||||
|
|
||||||
if (sender.DataContext is object content)
|
|
||||||
{
|
|
||||||
if (content is IConfirmation confirmation &&
|
|
||||||
!await confirmation.Confirm())
|
|
||||||
{
|
|
||||||
args.Cancel = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!args.Cancel)
|
|
||||||
{
|
|
||||||
if (content is IDeactivating deactivating)
|
|
||||||
{
|
|
||||||
await deactivating.OnDeactivating();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sender.AddHandler(Frame.NavigatingFromEvent, HandleNavigatingFrom);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NavigatedFrom(Control sender)
|
|
||||||
{
|
|
||||||
async void HandleNavigatedFrom(object? _,
|
|
||||||
NavigationEventArgs args)
|
|
||||||
{
|
|
||||||
sender.RemoveHandler(Frame.NavigatedFromEvent, HandleNavigatedFrom);
|
|
||||||
if (sender.DataContext is object content)
|
|
||||||
{
|
|
||||||
if (content is IDeactivated deactivated)
|
|
||||||
{
|
|
||||||
await deactivated.OnDeactivated();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (content is IDisposable disposable)
|
|
||||||
{
|
|
||||||
disposable.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sender.AddHandler(Frame.NavigatedFromEvent, HandleNavigatedFrom);
|
|
||||||
}
|
|
||||||
|
|
||||||
void NavigatedTo(Control sender)
|
void NavigatedTo(Control sender)
|
||||||
{
|
{
|
||||||
async void HandleNavigatedTo(object? _,
|
async void HandleNavigatedTo(object? _,
|
||||||
NavigationEventArgs __)
|
NavigationEventArgs __)
|
||||||
{
|
{
|
||||||
sender.RemoveHandler(Frame.NavigatedToEvent, HandleNavigatedTo);
|
sender.RemoveHandler(Frame.NavigatedToEvent, HandleNavigatedTo);
|
||||||
NavigatingFrom(sender);
|
|
||||||
|
|
||||||
|
async void HandleNavigatingFrom(object? _,
|
||||||
|
NavigatingCancelEventArgs args)
|
||||||
|
{
|
||||||
|
sender.RemoveHandler(Frame.NavigatingFromEvent, HandleNavigatingFrom);
|
||||||
|
control.Unloaded -= HandleUnloaded;
|
||||||
|
|
||||||
|
async void HandleNavigatedFrom(object? _,
|
||||||
|
NavigationEventArgs args)
|
||||||
|
{
|
||||||
|
sender.RemoveHandler(Frame.NavigatedFromEvent, HandleNavigatedFrom);
|
||||||
|
if (sender.DataContext is object content)
|
||||||
|
{
|
||||||
|
if (content is IDeactivated deactivated)
|
||||||
|
{
|
||||||
|
await deactivated.OnDeactivated();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (content is IDisposable disposable)
|
||||||
|
{
|
||||||
|
disposable.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.AddHandler(Frame.NavigatedFromEvent, HandleNavigatedFrom);
|
||||||
|
if (sender.DataContext is object content)
|
||||||
|
{
|
||||||
|
if (content is IConfirmation confirmation &&
|
||||||
|
!await confirmation.Confirm())
|
||||||
|
{
|
||||||
|
args.Cancel = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!args.Cancel)
|
||||||
|
{
|
||||||
|
if (content is IDeactivating deactivating)
|
||||||
|
{
|
||||||
|
await deactivating.OnDeactivating();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.AddHandler(Frame.NavigatingFromEvent, HandleNavigatingFrom);
|
||||||
if (sender.DataContext is object content)
|
if (sender.DataContext is object content)
|
||||||
{
|
{
|
||||||
if (content is IInitializer initializer)
|
if (content is IInitializer initializer)
|
||||||
@@ -90,6 +82,27 @@ public class FrameHandler :
|
|||||||
await activated.OnActivated();
|
await activated.OnActivated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async void HandleUnloaded(object? _, RoutedEventArgs __)
|
||||||
|
{
|
||||||
|
sender.RemoveHandler(Frame.NavigatingFromEvent, HandleNavigatingFrom);
|
||||||
|
control.Unloaded -= HandleUnloaded;
|
||||||
|
|
||||||
|
if (control.DataContext is object content)
|
||||||
|
{
|
||||||
|
if (content is IDeactivated deactivated)
|
||||||
|
{
|
||||||
|
await deactivated.OnDeactivated();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (content is IDisposable disposable)
|
||||||
|
{
|
||||||
|
disposable.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.Unloaded += HandleUnloaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
sender.AddHandler(Frame.NavigatedToEvent, HandleNavigatedTo);
|
sender.AddHandler(Frame.NavigatedToEvent, HandleNavigatedTo);
|
||||||
@@ -97,7 +110,30 @@ public class FrameHandler :
|
|||||||
|
|
||||||
control.DataContext = args.Content;
|
control.DataContext = args.Content;
|
||||||
NavigatedTo(control);
|
NavigatedTo(control);
|
||||||
frame.NavigateFromObject(control, new FrameNavigationOptions { TransitionInfoOverride = new SuppressNavigationTransitionInfo() });
|
|
||||||
|
FrameNavigationOptions navigationOptions = new();
|
||||||
|
if (args.Parameters is not null)
|
||||||
|
{
|
||||||
|
if (args.Parameters.TryGetValue("Transition", out object? transition))
|
||||||
|
{
|
||||||
|
switch($"{transition}")
|
||||||
|
{
|
||||||
|
case "FromLeft":
|
||||||
|
case "FromRight":
|
||||||
|
case "FromTop":
|
||||||
|
case "FromBottom":
|
||||||
|
navigationOptions.TransitionInfoOverride =
|
||||||
|
new SlideNavigationTransitionInfo
|
||||||
|
{
|
||||||
|
Effect = Enum.Parse<SlideNavigationTransitionEffect>($"{transition}")
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
frame.NavigateFromObject(control, navigationOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,6 +144,12 @@ public class FrameHandler :
|
|||||||
{
|
{
|
||||||
if (args.Context is Frame frame)
|
if (args.Context is Frame frame)
|
||||||
{
|
{
|
||||||
|
//NavigationTransitionInfo? navigationTransitionInfo = null;
|
||||||
|
//if (frame.Content is IBackwardNavigation navigation)
|
||||||
|
//{
|
||||||
|
// navigationTransitionInfo = navigation.Transition;
|
||||||
|
//}
|
||||||
|
|
||||||
frame.GoBack();
|
frame.GoBack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ public interface INavigationScope
|
|||||||
object? sender = null,
|
object? sender = null,
|
||||||
object? region = null,
|
object? region = null,
|
||||||
EventHandler? navigated = null,
|
EventHandler? navigated = null,
|
||||||
object[]? parameters = null);
|
IDictionary<string, object>? parameters = null);
|
||||||
|
|
||||||
void Back(object? region);
|
void Back(object? region);
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,8 @@ public class NavigateBackHandler(IComponentScopeProvider provider) :
|
|||||||
if (provider.Get(args.Scope ?? "Root")
|
if (provider.Get(args.Scope ?? "Root")
|
||||||
is ComponentScopeDescriptor descriptor)
|
is ComponentScopeDescriptor descriptor)
|
||||||
{
|
{
|
||||||
if (descriptor?.Services?.GetService<INavigationScope>() is INavigationScope navigationScope)
|
if (descriptor?.Services?.GetService<INavigationScope>() is
|
||||||
|
INavigationScope navigationScope)
|
||||||
{
|
{
|
||||||
navigationScope.Back(args.Context);
|
navigationScope.Back(args.Context);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ public record NavigateEventArgs(string Route,
|
|||||||
string? Scope = null,
|
string? Scope = null,
|
||||||
object? Sender = null,
|
object? Sender = null,
|
||||||
EventHandler? Navigated = null,
|
EventHandler? Navigated = null,
|
||||||
object[]? Parameters = null);
|
IDictionary<string, object>? Parameters = null);
|
||||||
|
|
||||||
public record NavigateEventArgs<TNavigation>(object Region,
|
public record NavigateEventArgs<TNavigation>(object Region,
|
||||||
object Template,
|
object Template,
|
||||||
object Content,
|
object Content,
|
||||||
object? Sender = null,
|
object? Sender = null,
|
||||||
object[]? Parameters = null);
|
IDictionary<string, object>? Parameters = null);
|
||||||
@@ -14,7 +14,7 @@ public class NavigationScope(IPublisher publisher,
|
|||||||
object? sender = null,
|
object? sender = null,
|
||||||
object? region = null,
|
object? region = null,
|
||||||
EventHandler? navigated = null,
|
EventHandler? navigated = null,
|
||||||
object[]? parameters = null)
|
IDictionary<string, object>? parameters = null)
|
||||||
{
|
{
|
||||||
if (region is null)
|
if (region is null)
|
||||||
{
|
{
|
||||||
@@ -32,20 +32,14 @@ public class NavigationScope(IPublisher publisher,
|
|||||||
if (contentTemplateDescriptorProvider.Get(segment)
|
if (contentTemplateDescriptorProvider.Get(segment)
|
||||||
is IContentTemplateDescriptor descriptor)
|
is IContentTemplateDescriptor descriptor)
|
||||||
{
|
{
|
||||||
Dictionary<string, object>? arguments = parameters?.OfType<KeyValuePair<string, object>>()
|
Dictionary<string, object>? arguments = parameters?.ToDictionary(x => x.Key, x => x.Value, StringComparer.InvariantCultureIgnoreCase) ?? [];
|
||||||
.ToDictionary(x => x.Key, x => x.Value, StringComparer.InvariantCultureIgnoreCase) ?? [];
|
object[]? resolvedArguments = parameters is not null ? [.. descriptor.ContentType
|
||||||
|
|
||||||
IEnumerable<object?>? mappedParameters = descriptor.ContentType
|
|
||||||
.GetConstructors()
|
.GetConstructors()
|
||||||
.FirstOrDefault()?
|
.FirstOrDefault()?
|
||||||
.GetParameters()
|
.GetParameters()
|
||||||
.Select(parameter => parameter?.Name is not null && arguments
|
.Select(x => x?.Name is not null && arguments
|
||||||
.TryGetValue(parameter.Name, out object? argument) ? argument : default)
|
.TryGetValue(x.Name, out object? argument) ? argument : default)
|
||||||
.Where(argument => argument is not null);
|
.Where(argument => argument is not null)] : [];
|
||||||
|
|
||||||
parameters = [.. parameters?.Where(x => x.GetType() != typeof(KeyValuePair<string, object>)) ??
|
|
||||||
Enumerable.Empty<object?>(),
|
|
||||||
.. mappedParameters ?? Enumerable.Empty<object?>()];
|
|
||||||
|
|
||||||
if (provider.GetRequiredKeyedService(descriptor.TemplateType, segment) is object view)
|
if (provider.GetRequiredKeyedService(descriptor.TemplateType, segment) is object view)
|
||||||
{
|
{
|
||||||
@@ -69,9 +63,9 @@ public class NavigationScope(IPublisher publisher,
|
|||||||
|
|
||||||
if (region is not null)
|
if (region is not null)
|
||||||
{
|
{
|
||||||
if ((parameters is { Length: > 0 }
|
if ((resolvedArguments is { Length: > 0 }
|
||||||
? factory.Create(descriptor.ContentType, parameters)
|
? factory.Create(descriptor.ContentType, resolvedArguments)
|
||||||
: provider.GetRequiredKeyedService(descriptor.ContentType, segment)) is object viewModel)
|
: provider.GetRequiredKeyedService(descriptor.ContentType, segment)) is object viewModel)
|
||||||
{
|
{
|
||||||
if (navigationProvider.Get(region is Type type ? type : region.GetType()) is INavigation navigation)
|
if (navigationProvider.Get(region is Type type ? type : region.GetType()) is INavigation navigation)
|
||||||
{
|
{
|
||||||
@@ -92,20 +86,20 @@ public class NavigationScope(IPublisher publisher,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Back(object? context)
|
public void Back(object? region)
|
||||||
{
|
{
|
||||||
if (context is not null)
|
if (region is not null)
|
||||||
{
|
{
|
||||||
navigationRegionProvider.TryGet(context, out context);
|
navigationRegionProvider.TryGet(region, out region);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (context is not null)
|
if (region is not null)
|
||||||
{
|
{
|
||||||
if (navigationProvider.Get(context is Type type ? type : context.GetType())
|
if (navigationProvider.Get(region is Type type ? type : region.GetType())
|
||||||
is INavigation navigation)
|
is INavigation navigation)
|
||||||
{
|
{
|
||||||
Type navigateType = typeof(NavigateBackEventArgs<>).MakeGenericType(navigation.Type);
|
Type navigateType = typeof(NavigateBackEventArgs<>).MakeGenericType(navigation.Type);
|
||||||
if (Activator.CreateInstance(navigateType, [context]) is object navigate)
|
if (Activator.CreateInstance(navigateType, [region]) is object navigate)
|
||||||
{
|
{
|
||||||
publisher.Publish(navigate);
|
publisher.Publish(navigate);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Metadata;
|
using Avalonia.Metadata;
|
||||||
using Avalonia.Xaml.Interactivity;
|
using Avalonia.Xaml.Interactivity;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using Toolkit.Foundation;
|
using Toolkit.Foundation;
|
||||||
|
|
||||||
namespace Toolkit.UI.Avalonia;
|
namespace Toolkit.UI.Avalonia;
|
||||||
@@ -10,12 +11,9 @@ public class NavigateAction :
|
|||||||
AvaloniaObject,
|
AvaloniaObject,
|
||||||
IAction
|
IAction
|
||||||
{
|
{
|
||||||
public static readonly DirectProperty<NavigateAction, ParameterBindingCollection> ParameterBindingsProperty =
|
public static readonly DirectProperty<NavigateAction, ParameterCollection> ParametersProperty =
|
||||||
AvaloniaProperty.RegisterDirect<NavigateAction, ParameterBindingCollection>(nameof(ParameterBindings),
|
AvaloniaProperty.RegisterDirect<NavigateAction, ParameterCollection>(nameof(Parameters),
|
||||||
x => x.ParameterBindings);
|
x => x.Parameters);
|
||||||
|
|
||||||
public static readonly StyledProperty<object[]?> ParametersProperty =
|
|
||||||
AvaloniaProperty.Register<NavigateAction, object[]?>(nameof(Parameters));
|
|
||||||
|
|
||||||
public static readonly StyledProperty<object> RegionProperty =
|
public static readonly StyledProperty<object> RegionProperty =
|
||||||
AvaloniaProperty.Register<NavigateAction, object>(nameof(Region));
|
AvaloniaProperty.Register<NavigateAction, object>(nameof(Region));
|
||||||
@@ -26,7 +24,7 @@ public class NavigateAction :
|
|||||||
public static readonly StyledProperty<string> ScopeProperty =
|
public static readonly StyledProperty<string> ScopeProperty =
|
||||||
AvaloniaProperty.Register<NavigateAction, string>(nameof(Scope));
|
AvaloniaProperty.Register<NavigateAction, string>(nameof(Scope));
|
||||||
|
|
||||||
private ParameterBindingCollection parameterCollection = [];
|
private ParameterCollection parameterCollection = [];
|
||||||
|
|
||||||
public event EventHandler? Navigated;
|
public event EventHandler? Navigated;
|
||||||
|
|
||||||
@@ -37,15 +35,9 @@ public class NavigateAction :
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Content]
|
[Content]
|
||||||
public ParameterBindingCollection ParameterBindings =>
|
public ParameterCollection Parameters =>
|
||||||
parameterCollection ??= [];
|
parameterCollection ??= [];
|
||||||
|
|
||||||
public object[]? Parameters
|
|
||||||
{
|
|
||||||
get => GetValue(ParametersProperty);
|
|
||||||
set => SetValue(ParametersProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Route
|
public string Route
|
||||||
{
|
{
|
||||||
get => GetValue(RouteProperty);
|
get => GetValue(RouteProperty);
|
||||||
@@ -68,11 +60,8 @@ public class NavigateAction :
|
|||||||
|
|
||||||
if (content.DataContext is IObservableViewModel observableViewModel)
|
if (content.DataContext is IObservableViewModel observableViewModel)
|
||||||
{
|
{
|
||||||
object[] parameters = [.. Parameters ?? Enumerable.Empty<object?>(),
|
ImmutableDictionary<string, object>? parameters = Parameters is { Count: > 0 } ? Parameters.ToImmutableDictionary(x => x.Key, x => x.Value) :
|
||||||
..
|
ImmutableDictionary<string, object>.Empty;
|
||||||
ParameterBindings is { Count: > 0 } ?
|
|
||||||
ParameterBindings.Select(binding => new KeyValuePair<string, object>(binding.Key, binding.Value)).ToArray() :
|
|
||||||
Enumerable.Empty<KeyValuePair<string, object>>()];
|
|
||||||
|
|
||||||
observableViewModel.Publisher.Publish(new NavigateEventArgs(Route, Region == this ? content : Region, Scope ?? null,
|
observableViewModel.Publisher.Publish(new NavigateEventArgs(Route, Region == this ? content : Region, Scope ?? null,
|
||||||
content.DataContext, Navigated, parameters));
|
content.DataContext, Navigated, parameters));
|
||||||
|
|||||||
@@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
namespace Toolkit.UI.Avalonia;
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
public class ParameterBinding :
|
public class Parameter :
|
||||||
AvaloniaObject
|
AvaloniaObject
|
||||||
{
|
{
|
||||||
public static readonly StyledProperty<string> KeyProperty =
|
public static readonly StyledProperty<string> KeyProperty =
|
||||||
AvaloniaProperty.Register<ParameterBinding, string>(nameof(Key));
|
AvaloniaProperty.Register<Parameter, string>(nameof(Key));
|
||||||
|
|
||||||
public static readonly StyledProperty<object> ValueProperty =
|
public static readonly StyledProperty<object> ValueProperty =
|
||||||
AvaloniaProperty.Register<ParameterBinding, object>(nameof(Value));
|
AvaloniaProperty.Register<Parameter, object>(nameof(Value));
|
||||||
|
|
||||||
public string Key
|
public string Key
|
||||||
{
|
{
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
using System.Collections.ObjectModel;
|
|
||||||
|
|
||||||
namespace Toolkit.UI.Avalonia;
|
|
||||||
|
|
||||||
public class ParameterBindingCollection :
|
|
||||||
ObservableCollection<ParameterBinding>;
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
using System.Collections.ObjectModel;
|
||||||
|
|
||||||
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
|
public class ParameterCollection :
|
||||||
|
ObservableCollection<Parameter>;
|
||||||
Reference in New Issue
Block a user