diff --git a/src/Maui/Prism.Maui/Common/MvvmHelpers.cs b/src/Maui/Prism.Maui/Common/MvvmHelpers.cs index 625879d6b..0754c73b9 100644 --- a/src/Maui/Prism.Maui/Common/MvvmHelpers.cs +++ b/src/Maui/Prism.Maui/Common/MvvmHelpers.cs @@ -88,12 +88,14 @@ private static void DestroyChildren(IView page) { DestroyPage(item); } + break; case NavigationPage navigationPage: foreach (var item in navigationPage.Navigation.NavigationStack.Reverse()) { DestroyPage(item); } + break; } } @@ -104,11 +106,12 @@ public static void DestroyWithModalStack(Page? page, IList modalStack) { DestroyPage(childPage); } + DestroyPage(page); } public static T? GetImplementerFromViewOrViewModel(object view) - where T : class + where T : class { if (view is T viewAsT) { @@ -281,8 +284,9 @@ public static void SetCurrentPageDelegate(Func getCurrentPageDelega { FlyoutPage flyout => GetTarget(flyout.Detail), TabbedPage tabbed => GetTarget(tabbed.CurrentPage), - NavigationPage navigation => GetTarget(navigation.CurrentPage), + NavigationPage navigation => GetTarget(navigation.CurrentPage) ?? navigation, ContentPage page => page, + null => null, _ => throw new NotSupportedException($"The page type '{target.GetType().FullName}' is not supported.") }; } @@ -298,12 +302,12 @@ public static void SetCurrentPageDelegate(Func getCurrentPageDelega { if (target is IDialogContainer) { - if (page.Parent is Page parentPage) + return page.Parent switch { - return GetTarget(parentPage); - } - - throw new InvalidOperationException("Unable to determine the current page."); + Page parentPage => GetTarget(parentPage), + Window window => GetTarget(window.Page), + _ => throw new InvalidOperationException("Unable to determine the current page.") + }; } return page.Parent switch diff --git a/tests/Maui/Prism.Maui.Tests/Fixtures/Common/MvvmHelperFixture.cs b/tests/Maui/Prism.Maui.Tests/Fixtures/Common/MvvmHelperFixture.cs new file mode 100644 index 000000000..83b7bd6c6 --- /dev/null +++ b/tests/Maui/Prism.Maui.Tests/Fixtures/Common/MvvmHelperFixture.cs @@ -0,0 +1,135 @@ +using Prism.Common; + +namespace Prism.Maui.Tests.Fixtures.Common; + +public class MvvmHelperFixture +{ + /// + /// This test was introduced to verify GH3143 + /// + /// Git Hub Issue 3143 + [Fact] + public async Task GetCurrentPageFromFlyoutPageWithModalReturnsDetailPage() + { + // Given + var flyout = new FlyoutPage + { Flyout = new ContentPage { Title = "Title" }, Detail = new NavigationPage(), }; + var window = new PrismWindow { Page = flyout }; + await window.Navigation.PushModalAsync(new DialogContainerPage()); + + // When + var result = MvvmHelpers.GetCurrentPage(window.Page); + + // Then + Assert.Equal(flyout.Detail, result); + } + + /// + /// This test was introduced to verify GH3143 + /// + /// Git Hub Issue 3143 + [Fact] + public async Task GetCurrentPageFromComplexFlyoutPageWithModalReturnsCorrectPage() + { + // Given + var expected = new ContentPage { Title = "D" }; + var navigationPage = new NavigationPage(); + await navigationPage.PushAsync(new ContentPage { Title = "A" }); + await navigationPage.PushAsync(new ContentPage { Title = "B" }); + await navigationPage.PushAsync(new ContentPage { Title = "C" }); + await navigationPage.PushAsync(expected); + + var window = new Window + { + Page = new FlyoutPage + { Flyout = new ContentPage { Title = "Title" }, Detail = navigationPage, } + }; + + await window.Navigation.PushModalAsync(new DialogContainerPage()); + + // When + var result = MvvmHelpers.GetCurrentPage(window.Page); + + // Then + Assert.Equal(expected, result); + } + + /// + /// This test was introduced to verify GH3143 + /// + /// Git Hub Issue 3143 + [Fact] + public async Task GetCurrentPageFromNavigationPageWithModalReturnsContentPage() + { + // Given + var expected = new ContentPage(); + var window = new Window { Page = new NavigationPage(expected) }; + await window.Navigation.PushModalAsync(new DialogContainerPage()); + + // When + var result = MvvmHelpers.GetCurrentPage(window.Page); + + // Then + Assert.Equal(expected, result); + } + + /// + /// This test was introduced to verify GH3143 + /// + /// Git Hub Issue 3143 + [Fact] + public async Task GetCurrentPageFromContentPageWithModalReturnsContentPage() + { + // Given + var expected = new ContentPage { Title = "Title" }; + var window = new Window { Page = expected }; + await window.Navigation.PushModalAsync(new DialogContainerPage()); + + // When + var result = MvvmHelpers.GetCurrentPage(window.Page); + + // Then + Assert.Equal(expected, result); + } + + /// + /// This test was introduced to verify GH3143 + /// + /// Git Hub Issue 3143 + [Fact(Skip = "System.InvalidOperationException\nBindableObject was not instantiated on a thread with a dispatcher nor does the current application have a dispatcher.")] + public async Task GetCurrentPageFromTabbedPageWithModalReturnsContentPage() + { + // Given + var expected = new ContentPage(); + var tabbedPage = new TabbedPage { Title = "Tab", Children = { expected }}; + var window = new Window { Page = tabbedPage }; + await window.Navigation.PushModalAsync(new DialogContainerPage()); + + // When + var result = MvvmHelpers.GetCurrentPage(window.Page); + + // Then + Assert.Equal(expected, result); + } + + /// + /// This test was introduced to verify GH3143 + /// + /// Git Hub Issue 3143 + [Fact(Skip = "System.InvalidOperationException\nBindableObject was not instantiated on a thread with a dispatcher nor does the current application have a dispatcher.")] + public async Task GetCurrentPageFromTabbedNavigationPageWithModalReturnsContentPage() + { + // Given + var expected = new ContentPage(); + var navigationPage = new NavigationPage(expected); + var tabbedPage = new TabbedPage { Title = "Tab", Children = { navigationPage }}; + var window = new Window { Page = tabbedPage }; + await window.Navigation.PushModalAsync(new DialogContainerPage()); + + // When + var result = MvvmHelpers.GetCurrentPage(window.Page); + + // Then + Assert.Equal(expected, result); + } +}