diff --git a/Toolkit.Avalonia/ClassicDesktopStyleApplicationHandler.cs b/Toolkit.Avalonia/ClassicDesktopStyleApplicationHandler.cs index 34af12b..a26247d 100644 --- a/Toolkit.Avalonia/ClassicDesktopStyleApplicationHandler.cs +++ b/Toolkit.Avalonia/ClassicDesktopStyleApplicationHandler.cs @@ -10,14 +10,18 @@ public class ClassicDesktopStyleApplicationHandler : { public void Handle(NavigateTemplateEventArgs args) { - if (Application.Current?.ApplicationLifetime is - IClassicDesktopStyleApplicationLifetime lifeTime) + if (Application.Current?.ApplicationLifetime + is not IClassicDesktopStyleApplicationLifetime lifeTime) { - if (args.Template is Window window) - { - lifeTime.MainWindow = window; - window.DataContext = args.Content; - } + return; } + + if (args.Template is not Window window) + { + return; + } + + lifeTime.MainWindow = window; + window.DataContext = args.Content; } } \ No newline at end of file diff --git a/Toolkit.Avalonia/ContentControlHandler.cs b/Toolkit.Avalonia/ContentControlHandler.cs index ca734ac..5fa9d45 100644 --- a/Toolkit.Avalonia/ContentControlHandler.cs +++ b/Toolkit.Avalonia/ContentControlHandler.cs @@ -9,50 +9,51 @@ public class ContentControlHandler : { public void Handle(NavigateTemplateEventArgs args) { - if (args.Region is ContentControl contentControl) + if (args.Region is not ContentControl contentControl) { - if (args.Template is Control control) + return; + } + + if (args.Template is not Control control) + { + return; + } + + void HandleLoaded(object? sender, RoutedEventArgs args) + { + control.Loaded -= HandleLoaded; + if (control.DataContext is object content) { - TaskCompletionSource taskCompletionSource = new(); - void HandleLoaded(object? sender, RoutedEventArgs args) + if (content is IActivation activation) { - control.Loaded -= HandleLoaded; - if (control.DataContext is object content) - { - if (content is IActivation activation) - { - activation.IsActive = true; - } - } - - taskCompletionSource.SetResult(); + activation.IsActive = true; } - - void HandleUnloaded(object? sender, RoutedEventArgs args) - { - control.Unloaded -= HandleLoaded; - if (control.DataContext is object content) - { - if (content is IActivation activation) - { - activation.IsActive = false; - } - - if (content is IDisposable disposable) - { - disposable.Dispose(); - } - } - } - - control.Loaded += HandleLoaded; - control.Unloaded += HandleUnloaded; - - control.DataContext = args.Content; - - contentControl.Content = null; - contentControl.Content = control; } } + + void HandleUnloaded(object? sender, RoutedEventArgs args) + { + control.Unloaded -= HandleLoaded; + if (control.DataContext is object content) + { + if (content is IActivation activation) + { + activation.IsActive = false; + } + + if (content is IDisposable disposable) + { + disposable.Dispose(); + } + } + } + + control.Loaded += HandleLoaded; + control.Unloaded += HandleUnloaded; + + control.DataContext = args.Content; + + contentControl.Content = null; + contentControl.Content = control; } } \ No newline at end of file diff --git a/Toolkit.Avalonia/ContentDialogHandler.cs b/Toolkit.Avalonia/ContentDialogHandler.cs index f269bd6..f720d25 100644 --- a/Toolkit.Avalonia/ContentDialogHandler.cs +++ b/Toolkit.Avalonia/ContentDialogHandler.cs @@ -114,9 +114,6 @@ public class ContentDialogHandler : dialog.SecondaryButtonClick += HandleSecondaryButtonClick; await dialog.ShowAsync(); - - dialog.PrimaryButtonClick += HandlePrimaryButtonClick; - dialog.SecondaryButtonClick += HandleSecondaryButtonClick; } } } \ No newline at end of file diff --git a/Toolkit.Avalonia/FrameHandler.cs b/Toolkit.Avalonia/FrameHandler.cs index 7a65c6a..96958cd 100644 --- a/Toolkit.Avalonia/FrameHandler.cs +++ b/Toolkit.Avalonia/FrameHandler.cs @@ -13,190 +13,195 @@ public class FrameHandler(ITransientNavigationStore navigationStore) : { public void Handle(NavigateTemplateEventArgs args) { - if (args.Region is Frame frame) + if (args.Region is not Frame frame) { - frame.NavigationPageFactory ??= new NavigationPageFactory(); - if (args.Template is Control control) + return; + } + + if (args.Template is not Control control) + { + return; + } + + frame.NavigationPageFactory ??= new NavigationPageFactory(); + + void Navigated(Control sender) + { + void HandleNavigatedTo(object? _, NavigationEventArgs __) { - void Navigated(Control sender) + async void HandleNavigatingFrom(object? _, NavigatingCancelEventArgs args) { - void HandleNavigatedTo(object? _, NavigationEventArgs __) + sender.RemoveHandler(Frame.NavigatingFromEvent, HandleNavigatingFrom); + control.Unloaded -= HandleUnloaded; + + void HandleNavigatedFrom(object? _, NavigationEventArgs args) { - async void HandleNavigatingFrom(object? _, NavigatingCancelEventArgs args) - { - sender.RemoveHandler(Frame.NavigatingFromEvent, HandleNavigatingFrom); - control.Unloaded -= HandleUnloaded; - - void HandleNavigatedFrom(object? _, NavigationEventArgs args) - { - sender.RemoveHandler(Frame.NavigatedFromEvent, HandleNavigatedFrom); - if (sender.DataContext is object content) - { - if (content is IActivation activation) - { - activation.IsActive = false; - } - - if (content is IDisposable disposable) - { - FrameNavigationOptions? options = navigationStore.Get(frame); - if (options is not FrameNavigationOptions frameOptions || - !frameOptions.IsNavigationStackEnabled) - { - disposable.Dispose(); - } - } - } - } - - sender.AddHandler(Frame.NavigatedFromEvent, HandleNavigatedFrom); - - if (sender.DataContext is object content) - { - if (content is IConfirmation confirmation && - !await confirmation.Confirm()) - { - args.Cancel = true; - } - } - } - - sender.AddHandler(Frame.NavigatingFromEvent, HandleNavigatingFrom); + sender.RemoveHandler(Frame.NavigatedFromEvent, HandleNavigatedFrom); if (sender.DataContext is object content) { if (content is IActivation activation) { - activation.IsActive = true; + activation.IsActive = false; } - } - void HandleUnloaded(object? _, RoutedEventArgs __) - { - sender.RemoveHandler(Frame.NavigatedToEvent, HandleNavigatedTo); - sender.RemoveHandler(Frame.NavigatingFromEvent, HandleNavigatingFrom); - - control.Unloaded -= HandleUnloaded; - - if (control.DataContext is object content) + if (content is IDisposable disposable) { - if (content is IActivation activation) - { - activation.IsActive = true; - } - - if (content is IDisposable disposable) + FrameNavigationOptions? options = navigationStore.Get(frame); + if (options is not FrameNavigationOptions frameOptions || + !frameOptions.IsNavigationStackEnabled) { disposable.Dispose(); } } } - - sender.Unloaded += HandleUnloaded; } - sender.AddHandler(Frame.NavigatedToEvent, HandleNavigatedTo); - } + sender.AddHandler(Frame.NavigatedFromEvent, HandleNavigatedFrom); - control.DataContext = args.Content; - - FrameNavigationOptions navigationOptions = new(); - List postNavigateActions = []; - - void CleanUp(int start, int end) - { - int startIndex = Math.Max(0, start - 1); - int endIndex = Math.Min(frame.BackStack.Count - 1, end - 1); - - for (int i = endIndex; i >= startIndex; i--) + if (sender.DataContext is object content) { - PageStackEntry? entry = frame.BackStack[i]; - if (entry.Context is Control control) + if (content is IConfirmation confirmation && + !await confirmation.Confirm()) { - if (control.DataContext is IDisposable disposable) - { - disposable.Dispose(); - } - } - - frame.BackStack.RemoveAt(i); - } - } - - if (args.Parameters is not null) - { - if (args.Parameters.TryGetValue("Transition", out object? transition)) - { - switch ($"{transition}") - { - case "Suppress": - navigationOptions.TransitionInfoOverride = new SuppressNavigationTransitionInfo(); - break; - - case "FromLeft": - case "FromRight": - case "FromTop": - case "FromBottom": - navigationOptions.TransitionInfoOverride = new SlideNavigationTransitionInfo - { - Effect = Enum.Parse($"{transition}") - }; - break; - } - } - - if (args.Parameters.TryGetValue("IsBackStackEnabled", out object? isBackStackEnabled)) - { - if (isBackStackEnabled is bool value) - { - navigationOptions.IsNavigationStackEnabled = value; - } - } - - if (args.Parameters.TryGetValue("ClearBackStack", out object? clearBackStack)) - { - if (clearBackStack is bool clearBool) - { - if (clearBool) - { - postNavigateActions.Add(() => CleanUp(1, frame.BackStack.Count)); - } - } - - if (clearBackStack is string clearString) - { - if (clearString.StartsWith('[') && clearString.EndsWith(']') && clearString.Contains('-')) - { - string range = clearString.Trim('[', ']'); - string[] parts = range.Split('-'); - - if (parts.Length == 2 && int.TryParse(parts[0], out int start) && - int.TryParse(parts[1], out int end)) - { - postNavigateActions.Add(() => CleanUp(start, end)); - } - else - { - postNavigateActions.Add(() => CleanUp(1, frame.BackStack.Count)); - } - } - else - { - postNavigateActions.Add(() => CleanUp(1, frame.BackStack.Count)); - } + args.Cancel = true; } } } - Navigated(control); - - navigationStore.Set(frame, navigationOptions); - frame.NavigateFromObject(control, navigationOptions); - - foreach (Action postAction in postNavigateActions) + sender.AddHandler(Frame.NavigatingFromEvent, HandleNavigatingFrom); + if (sender.DataContext is object content) { - postAction.Invoke(); + if (content is IActivation activation) + { + activation.IsActive = true; + } + } + + void HandleUnloaded(object? _, RoutedEventArgs __) + { + sender.RemoveHandler(Frame.NavigatedToEvent, HandleNavigatedTo); + sender.RemoveHandler(Frame.NavigatingFromEvent, HandleNavigatingFrom); + + control.Unloaded -= HandleUnloaded; + + if (control.DataContext is object content) + { + if (content is IActivation activation) + { + activation.IsActive = true; + } + + if (content is IDisposable disposable) + { + disposable.Dispose(); + } + } + } + + sender.Unloaded += HandleUnloaded; + } + + sender.AddHandler(Frame.NavigatedToEvent, HandleNavigatedTo); + } + + control.DataContext = args.Content; + + FrameNavigationOptions navigationOptions = new(); + List postNavigateActions = []; + + void CleanUp(int start, int end) + { + int startIndex = Math.Max(0, start - 1); + int endIndex = Math.Min(frame.BackStack.Count - 1, end - 1); + + for (int i = endIndex; i >= startIndex; i--) + { + PageStackEntry? entry = frame.BackStack[i]; + if (entry.Context is Control control) + { + if (control.DataContext is IDisposable disposable) + { + disposable.Dispose(); + } + } + + frame.BackStack.RemoveAt(i); + } + } + + if (args.Parameters is not null) + { + if (args.Parameters.TryGetValue("Transition", out object? transition)) + { + switch ($"{transition}") + { + case "Suppress": + navigationOptions.TransitionInfoOverride = new SuppressNavigationTransitionInfo(); + break; + + case "FromLeft": + case "FromRight": + case "FromTop": + case "FromBottom": + navigationOptions.TransitionInfoOverride = new SlideNavigationTransitionInfo + { + Effect = Enum.Parse($"{transition}") + }; + break; } } + + if (args.Parameters.TryGetValue("IsBackStackEnabled", out object? isBackStackEnabled)) + { + if (isBackStackEnabled is bool value) + { + navigationOptions.IsNavigationStackEnabled = value; + } + } + + if (args.Parameters.TryGetValue("ClearBackStack", out object? clearBackStack)) + { + if (clearBackStack is bool clearBool) + { + if (clearBool) + { + postNavigateActions.Add(() => CleanUp(1, frame.BackStack.Count)); + } + } + + if (clearBackStack is string clearString) + { + if (clearString.StartsWith('[') && clearString.EndsWith(']') && clearString.Contains('-')) + { + string range = clearString.Trim('[', ']'); + string[] parts = range.Split('-'); + + if (parts.Length == 2 && int.TryParse(parts[0], out int start) && + int.TryParse(parts[1], out int end)) + { + postNavigateActions.Add(() => CleanUp(start, end)); + } + else + { + postNavigateActions.Add(() => CleanUp(1, frame.BackStack.Count)); + } + } + else + { + postNavigateActions.Add(() => CleanUp(1, frame.BackStack.Count)); + } + } + } + } + + Navigated(control); + + navigationStore.Set(frame, navigationOptions); + frame.NavigateFromObject(control, navigationOptions); + + foreach (Action postAction in postNavigateActions) + { + postAction.Invoke(); } } diff --git a/Toolkit.Foundation/NavigateEventArgs.cs b/Toolkit.Foundation/NavigateEventArgs.cs index ced7baf..f071fea 100644 --- a/Toolkit.Foundation/NavigateEventArgs.cs +++ b/Toolkit.Foundation/NavigateEventArgs.cs @@ -6,10 +6,3 @@ public record NavigateEventArgs(string Route, object? Sender = null, EventHandler? Navigated = null, IDictionary? Parameters = null); - - -public record NavigateTemplateEventArgs(object Region, - object Template, - object Content, - object? Sender = null, - IDictionary? Parameters = null); \ No newline at end of file diff --git a/Toolkit.Foundation/NavigateTemplateEventArgs.cs b/Toolkit.Foundation/NavigateTemplateEventArgs.cs new file mode 100644 index 0000000..dffde18 --- /dev/null +++ b/Toolkit.Foundation/NavigateTemplateEventArgs.cs @@ -0,0 +1,7 @@ +namespace Toolkit.Foundation; + +public record NavigateTemplateEventArgs(object Region, + object Template, + object Content, + object? Sender = null, + IDictionary? Parameters = null); \ No newline at end of file diff --git a/Toolkit.Foundation/Navigation.cs b/Toolkit.Foundation/Navigation.cs index f2ef62b..b021a5b 100644 --- a/Toolkit.Foundation/Navigation.cs +++ b/Toolkit.Foundation/Navigation.cs @@ -37,8 +37,7 @@ public class Navigation(IServiceProvider provider, .GetConstructors() .FirstOrDefault()? .GetParameters() - .Select(x => - x?.Name is not null && arguments is not null && arguments.TryGetValue(x.Name, out object? argument) + .Select(x => x?.Name is not null && arguments is not null && arguments.TryGetValue(x.Name, out object? argument) ? argument : null) .Where(argument => argument is not null) @@ -70,9 +69,7 @@ public class Navigation(IServiceProvider provider, object? content = contentFactory.Create(descriptor, resolvedArguments); if (content is not null) { - Type navigationType = region is Type type ? type : region.GetType(); - - messenger.Send(new NavigateTemplateEventArgs(region, template, content, sender, parameters), navigationType.Name); + messenger.Send(new NavigateTemplateEventArgs(region, template, content, sender, parameters), region is string ? $"{region}" : region.GetType().Name); if (currentSegmentIndex == segmentCount) { navigated?.Invoke(this, EventArgs.Empty); diff --git a/Toolkit.UI.WinUI/NavigateAction.cs b/Toolkit.UI.WinUI/NavigateAction.cs index e05d488..ec18450 100644 --- a/Toolkit.UI.WinUI/NavigateAction.cs +++ b/Toolkit.UI.WinUI/NavigateAction.cs @@ -75,7 +75,7 @@ public class NavigateAction : ImmutableDictionary.Empty; observableViewModel.Messenger.Send(new NavigateEventArgs(Route, Region.Equals(this) ? content : Region, Scope ?? null, - content.DataContext, Navigated, parameters)); + content, Navigated, parameters)); } } diff --git a/Toolkit.WinUI/ContentControlHandler.cs b/Toolkit.WinUI/ContentControlHandler.cs index 12184b9..aeb4967 100644 --- a/Toolkit.WinUI/ContentControlHandler.cs +++ b/Toolkit.WinUI/ContentControlHandler.cs @@ -9,50 +9,49 @@ public class ContentControlHandler : { public void Handle(NavigateTemplateEventArgs args) { - if (args.Region is ContentControl contentControl) + if (args.Region is not ContentControl contentControl) { - if (args.Template is Control control) + return; + } + + if (args.Template is not Control control) + { + return; + } + + void HandleLoaded(object? sender, RoutedEventArgs args) + { + control.Loaded -= HandleLoaded; + if (control.DataContext is object content) { - TaskCompletionSource taskCompletionSource = new(); - void HandleLoaded(object? sender, RoutedEventArgs args) + if (content is IActivation activation) { - control.Loaded -= HandleLoaded; - if (control.DataContext is object content) - { - if (content is IActivation activation) - { - activation.IsActive = true; - } - } - - taskCompletionSource.SetResult(); + activation.IsActive = true; } - - void HandleUnloaded(object? sender, RoutedEventArgs args) - { - control.Unloaded -= HandleLoaded; - if (control.DataContext is object content) - { - if (content is IActivation activation) - { - activation.IsActive = false; - } - - if (content is IDisposable disposable) - { - disposable.Dispose(); - } - } - } - - control.Loaded += HandleLoaded; - control.Unloaded += HandleUnloaded; - - control.DataContext = args.Content; - - contentControl.Content = null; - contentControl.Content = control; } } + + void HandleUnloaded(object? sender, RoutedEventArgs args) + { + control.Unloaded -= HandleLoaded; + if (control.DataContext is object content) + { + if (content is IActivation activation) + { + activation.IsActive = false; + } + + if (content is IDisposable disposable) + { + disposable.Dispose(); + } + } + } + + control.Loaded += HandleLoaded; + control.Unloaded += HandleUnloaded; + + control.DataContext = args.Content; + contentControl.Content = control; } } diff --git a/Toolkit.WinUI/ContentDialogHandler.cs b/Toolkit.WinUI/ContentDialogHandler.cs index 421935c..fe80451 100644 --- a/Toolkit.WinUI/ContentDialogHandler.cs +++ b/Toolkit.WinUI/ContentDialogHandler.cs @@ -1,4 +1,5 @@ -using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; using Toolkit.Foundation; namespace Toolkit.WinUI; @@ -8,111 +9,118 @@ public class ContentDialogHandler : { public async void Handle(NavigateTemplateEventArgs args) { - if (args.Template is ContentDialog dialog) + if (args.Template is not ContentDialog dialog) { - dialog.DataContext = args.Content; - - async void HandlePrimaryButtonClick(ContentDialog sender, - ContentDialogButtonClickEventArgs args) - { - dialog.PrimaryButtonClick -= HandlePrimaryButtonClick; - if (dialog.DataContext is object content) - { - if (content is IPrimaryConfirmation primaryConfirmation) - { - ContentDialogButtonClickDeferral deferral = args.GetDeferral(); - if (!await primaryConfirmation.ConfirmPrimary()) - { - args.Cancel = true; - dialog.PrimaryButtonClick += HandlePrimaryButtonClick; - } - - deferral.Complete(); - } - } - } - - async void HandleSecondaryButtonClick(ContentDialog sender, - ContentDialogButtonClickEventArgs args) - { - dialog.SecondaryButtonClick -= HandleSecondaryButtonClick; - if (dialog.DataContext is object content) - { - if (content is ISecondaryConfirmation secondaryConfirmation) - { - ContentDialogButtonClickDeferral deferral = args.GetDeferral(); - if (!await secondaryConfirmation.ConfirmSecondary()) - { - args.Cancel = true; - dialog.SecondaryButtonClick += HandleSecondaryButtonClick; - } - - deferral.Complete(); - } - } - } - - async void HandleClosing(ContentDialog sender, - ContentDialogClosingEventArgs args) - { - if (args.Result is ContentDialogResult.Primary || - args.Result is ContentDialogResult.Secondary) - { - dialog.Closing -= HandleClosing; - if (dialog.DataContext is object content) - { - if (content is IConfirmation confirmation) - { - ContentDialogClosingDeferral deferral = args.GetDeferral(); - if (!await confirmation.Confirm()) - { - args.Cancel = true; - dialog.Closing += HandleClosing; - } - - deferral.Complete(); - } - } - } - } - - void HandleOpened(ContentDialog sender, - ContentDialogOpenedEventArgs args) - { - dialog.Opened -= HandleOpened; - if (dialog.DataContext is object content) - { - if (content is IActivation activation) - { - activation.IsActive = true; - } - } - } - - void HandleClosed(ContentDialog sender, - ContentDialogClosedEventArgs args) - { - dialog.Closed -= HandleClosed; - if (dialog.DataContext is object content) - { - if (content is IActivation activation) - { - activation.IsActive = false; - } - } - } - - dialog.Opened += HandleOpened; - dialog.Closing += HandleClosing; - dialog.Closed += HandleClosed; - - dialog.PrimaryButtonClick += HandlePrimaryButtonClick; - dialog.SecondaryButtonClick += HandleSecondaryButtonClick; - - await dialog.ShowAsync(); - - dialog.PrimaryButtonClick += HandlePrimaryButtonClick; - dialog.SecondaryButtonClick += HandleSecondaryButtonClick; + return; } + + if (args.Sender is not Control parent) + { + return; + } + + dialog.XamlRoot = parent.XamlRoot; + dialog.Style = Application.Current.Resources["DefaultContentDialogStyle"] as Style; + + dialog.DataContext = args.Content; + + async void HandlePrimaryButtonClick(ContentDialog sender, + ContentDialogButtonClickEventArgs args) + { + dialog.PrimaryButtonClick -= HandlePrimaryButtonClick; + if (dialog.DataContext is object content) + { + if (content is IPrimaryConfirmation primaryConfirmation) + { + ContentDialogButtonClickDeferral deferral = args.GetDeferral(); + if (!await primaryConfirmation.ConfirmPrimary()) + { + args.Cancel = true; + dialog.PrimaryButtonClick += HandlePrimaryButtonClick; + } + + deferral.Complete(); + } + } + } + + async void HandleSecondaryButtonClick(ContentDialog sender, + ContentDialogButtonClickEventArgs args) + { + dialog.SecondaryButtonClick -= HandleSecondaryButtonClick; + if (dialog.DataContext is object content) + { + if (content is ISecondaryConfirmation secondaryConfirmation) + { + ContentDialogButtonClickDeferral deferral = args.GetDeferral(); + if (!await secondaryConfirmation.ConfirmSecondary()) + { + args.Cancel = true; + dialog.SecondaryButtonClick += HandleSecondaryButtonClick; + } + + deferral.Complete(); + } + } + } + + async void HandleClosing(ContentDialog sender, + ContentDialogClosingEventArgs args) + { + if (args.Result is ContentDialogResult.Primary || + args.Result is ContentDialogResult.Secondary) + { + dialog.Closing -= HandleClosing; + if (dialog.DataContext is object content) + { + if (content is IConfirmation confirmation) + { + ContentDialogClosingDeferral deferral = args.GetDeferral(); + if (!await confirmation.Confirm()) + { + args.Cancel = true; + dialog.Closing += HandleClosing; + } + + deferral.Complete(); + } + } + } + } + + void HandleOpened(ContentDialog sender, + ContentDialogOpenedEventArgs args) + { + dialog.Opened -= HandleOpened; + if (dialog.DataContext is object content) + { + if (content is IActivation activation) + { + activation.IsActive = true; + } + } + } + + void HandleClosed(ContentDialog sender, + ContentDialogClosedEventArgs args) + { + dialog.Closed -= HandleClosed; + if (dialog.DataContext is object content) + { + if (content is IActivation activation) + { + activation.IsActive = false; + } + } + } + + dialog.Opened += HandleOpened; + dialog.Closing += HandleClosing; + dialog.Closed += HandleClosed; + + dialog.PrimaryButtonClick += HandlePrimaryButtonClick; + dialog.SecondaryButtonClick += HandleSecondaryButtonClick; + + await dialog.ShowAsync(); } } \ No newline at end of file