Skip to content

Commit

Permalink
Merge pull request #3147 from RLittlesII/gh/3143
Browse files Browse the repository at this point in the history
fix: GetCurrentPage for PrismWindow.Page throwing exception
  • Loading branch information
dansiegel authored May 30, 2024
2 parents 3125e20 + c007c9f commit 2d9cf89
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 7 deletions.
18 changes: 11 additions & 7 deletions src/Maui/Prism.Maui/Common/MvvmHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand All @@ -104,11 +106,12 @@ public static void DestroyWithModalStack(Page? page, IList<Page?> modalStack)
{
DestroyPage(childPage);
}

DestroyPage(page);
}

public static T? GetImplementerFromViewOrViewModel<T>(object view)
where T : class
where T : class
{
if (view is T viewAsT)
{
Expand Down Expand Up @@ -281,8 +284,9 @@ public static void SetCurrentPageDelegate(Func<Page, Page?> 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.")
};
}
Expand All @@ -298,12 +302,12 @@ public static void SetCurrentPageDelegate(Func<Page, Page?> 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
Expand Down
135 changes: 135 additions & 0 deletions tests/Maui/Prism.Maui.Tests/Fixtures/Common/MvvmHelperFixture.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
using Prism.Common;

namespace Prism.Maui.Tests.Fixtures.Common;

public class MvvmHelperFixture
{
/// <summary>
/// This test was introduced to verify GH3143
/// </summary>
/// <a href="https://github.com/PrismLibrary/Prism/issues/3143">Git Hub Issue 3143</a>
[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);
}

/// <summary>
/// This test was introduced to verify GH3143
/// </summary>
/// <a href="https://github.com/PrismLibrary/Prism/issues/3143">Git Hub Issue 3143</a>
[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);
}

/// <summary>
/// This test was introduced to verify GH3143
/// </summary>
/// <a href="https://github.com/PrismLibrary/Prism/issues/3143">Git Hub Issue 3143</a>
[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);
}

/// <summary>
/// This test was introduced to verify GH3143
/// </summary>
/// <a href="https://github.com/PrismLibrary/Prism/issues/3143">Git Hub Issue 3143</a>
[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);
}

/// <summary>
/// This test was introduced to verify GH3143
/// </summary>
/// <a href="https://github.com/PrismLibrary/Prism/issues/3143">Git Hub Issue 3143</a>
[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);
}

/// <summary>
/// This test was introduced to verify GH3143
/// </summary>
/// <a href="https://github.com/PrismLibrary/Prism/issues/3143">Git Hub Issue 3143</a>
[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);
}
}

0 comments on commit 2d9cf89

Please sign in to comment.