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