From 930367fab0f2066067dcaab9ad579636e5d994af Mon Sep 17 00:00:00 2001 From: textGamex Date: Sat, 27 Jul 2024 18:50:19 +0800 Subject: [PATCH 1/2] fix: failing to correctly trigger the methods of the INavigationAware interface. when both the View and ViewModel inherit from the INavigationAware interface, only the OnNavigatedToAsync/OnNavigatedFromAsync methods of the View are triggered --- .../NavigationViewContentPresenter.cs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/Wpf.Ui/Controls/NavigationView/NavigationViewContentPresenter.cs b/src/Wpf.Ui/Controls/NavigationView/NavigationViewContentPresenter.cs index a0a3a34e8..a769c9caf 100644 --- a/src/Wpf.Ui/Controls/NavigationView/NavigationViewContentPresenter.cs +++ b/src/Wpf.Ui/Controls/NavigationView/NavigationViewContentPresenter.cs @@ -182,12 +182,27 @@ private void ApplyTransitionEffectToNavigatedPage(object content) _ = TransitionAnimationProvider.ApplyTransition(content, Transition, TransitionDuration); } + [System.Diagnostics.CodeAnalysis.SuppressMessage( + "ReSharper", + "SuspiciousTypeConversion.Global", + Justification = "The library user might make a class inherit from both FrameworkElement and INavigationAware at the same time." + )] private static void NotifyContentAboutNavigatingTo(object content) { switch (content) { + // The order in which the OnNavigatedToAsync methods of View and ViewModel are called is not guaranteed case INavigationAware navigationAwareNavigationContent: _ = Task.Run(navigationAwareNavigationContent.OnNavigatedToAsync).ConfigureAwait(false); + if ( + navigationAwareNavigationContent + is FrameworkElement { DataContext: INavigationAware viewModel } + && !ReferenceEquals(viewModel, navigationAwareNavigationContent) + ) + { + _ = Task.Run(viewModel.OnNavigatedToAsync).ConfigureAwait(false); + } + break; case INavigableView { ViewModel: INavigationAware navigationAwareNavigableViewViewModel }: _ = Task.Run(navigationAwareNavigableViewViewModel.OnNavigatedToAsync).ConfigureAwait(false); @@ -198,12 +213,27 @@ private static void NotifyContentAboutNavigatingTo(object content) } } + [System.Diagnostics.CodeAnalysis.SuppressMessage( + "ReSharper", + "SuspiciousTypeConversion.Global", + Justification = "The library user might make a class inherit from both FrameworkElement and INavigationAware at the same time." + )] private static void NotifyContentAboutNavigatingFrom(object content) { switch (content) { + // The order in which the OnNavigatedFromAsync methods of View and ViewModel are called is not guaranteed case INavigationAware navigationAwareNavigationContent: _ = Task.Run(navigationAwareNavigationContent.OnNavigatedFromAsync).ConfigureAwait(false); + if ( + navigationAwareNavigationContent + is FrameworkElement { DataContext: INavigationAware viewModel } + && !ReferenceEquals(viewModel, navigationAwareNavigationContent) + ) + { + _ = Task.Run(viewModel.OnNavigatedFromAsync).ConfigureAwait(false); + } + break; case INavigableView { ViewModel: INavigationAware navigationAwareNavigableViewViewModel }: _ = Task.Run(navigationAwareNavigableViewViewModel.OnNavigatedFromAsync) From d70e6403a3b7a9cc9868dddef34ae2f3386cd9c0 Mon Sep 17 00:00:00 2001 From: textGamex Date: Sat, 27 Jul 2024 19:11:03 +0800 Subject: [PATCH 2/2] refactor: reduce code duplication. --- .../NavigationViewContentPresenter.cs | 45 +++++-------------- 1 file changed, 12 insertions(+), 33 deletions(-) diff --git a/src/Wpf.Ui/Controls/NavigationView/NavigationViewContentPresenter.cs b/src/Wpf.Ui/Controls/NavigationView/NavigationViewContentPresenter.cs index a769c9caf..66817641e 100644 --- a/src/Wpf.Ui/Controls/NavigationView/NavigationViewContentPresenter.cs +++ b/src/Wpf.Ui/Controls/NavigationView/NavigationViewContentPresenter.cs @@ -182,35 +182,14 @@ private void ApplyTransitionEffectToNavigatedPage(object content) _ = TransitionAnimationProvider.ApplyTransition(content, Transition, TransitionDuration); } - [System.Diagnostics.CodeAnalysis.SuppressMessage( - "ReSharper", - "SuspiciousTypeConversion.Global", - Justification = "The library user might make a class inherit from both FrameworkElement and INavigationAware at the same time." - )] private static void NotifyContentAboutNavigatingTo(object content) { - switch (content) - { - // The order in which the OnNavigatedToAsync methods of View and ViewModel are called is not guaranteed - case INavigationAware navigationAwareNavigationContent: - _ = Task.Run(navigationAwareNavigationContent.OnNavigatedToAsync).ConfigureAwait(false); - if ( - navigationAwareNavigationContent - is FrameworkElement { DataContext: INavigationAware viewModel } - && !ReferenceEquals(viewModel, navigationAwareNavigationContent) - ) - { - _ = Task.Run(viewModel.OnNavigatedToAsync).ConfigureAwait(false); - } + NotifyContentAboutNavigating(content, navigationAware => navigationAware.OnNavigatedToAsync()); + } - break; - case INavigableView { ViewModel: INavigationAware navigationAwareNavigableViewViewModel }: - _ = Task.Run(navigationAwareNavigableViewViewModel.OnNavigatedToAsync).ConfigureAwait(false); - break; - case FrameworkElement { DataContext: INavigationAware navigationAwareCurrentContent }: - _ = Task.Run(navigationAwareCurrentContent.OnNavigatedToAsync).ConfigureAwait(false); - break; - } + private static void NotifyContentAboutNavigatingFrom(object content) + { + NotifyContentAboutNavigating(content, navigationAware => navigationAware.OnNavigatedFromAsync()); } [System.Diagnostics.CodeAnalysis.SuppressMessage( @@ -218,29 +197,29 @@ private static void NotifyContentAboutNavigatingTo(object content) "SuspiciousTypeConversion.Global", Justification = "The library user might make a class inherit from both FrameworkElement and INavigationAware at the same time." )] - private static void NotifyContentAboutNavigatingFrom(object content) + private static void NotifyContentAboutNavigating(object content, Func function) { switch (content) { - // The order in which the OnNavigatedFromAsync methods of View and ViewModel are called is not guaranteed + // The order in which the OnNavigatedToAsync/OnNavigatedFromAsync methods of View and ViewModel are called + // is not guaranteed case INavigationAware navigationAwareNavigationContent: - _ = Task.Run(navigationAwareNavigationContent.OnNavigatedFromAsync).ConfigureAwait(false); + _ = Task.Run(() => function(navigationAwareNavigationContent)).ConfigureAwait(false); if ( navigationAwareNavigationContent is FrameworkElement { DataContext: INavigationAware viewModel } && !ReferenceEquals(viewModel, navigationAwareNavigationContent) ) { - _ = Task.Run(viewModel.OnNavigatedFromAsync).ConfigureAwait(false); + _ = Task.Run(() => function(viewModel)).ConfigureAwait(false); } break; case INavigableView { ViewModel: INavigationAware navigationAwareNavigableViewViewModel }: - _ = Task.Run(navigationAwareNavigableViewViewModel.OnNavigatedFromAsync) - .ConfigureAwait(false); + _ = Task.Run(() => function(navigationAwareNavigableViewViewModel)).ConfigureAwait(false); break; case FrameworkElement { DataContext: INavigationAware navigationAwareCurrentContent }: - _ = Task.Run(navigationAwareCurrentContent.OnNavigatedFromAsync).ConfigureAwait(false); + _ = Task.Run(() => function(navigationAwareCurrentContent)).ConfigureAwait(false); break; } }