From 6b67e7f99b5c0a912e6de34982b69620054bf6f5 Mon Sep 17 00:00:00 2001
From: Brian Lagunas <835562+brianlagunas@users.noreply.github.com>
Date: Thu, 4 Jul 2024 11:47:27 -0600
Subject: [PATCH 1/6] fixed #3178
---
.../Controls/PrismNavigationPage.cs | 26 +++++--------------
1 file changed, 7 insertions(+), 19 deletions(-)
diff --git a/src/Maui/Prism.Maui/Controls/PrismNavigationPage.cs b/src/Maui/Prism.Maui/Controls/PrismNavigationPage.cs
index 78964d7ac..94bbd25b9 100644
--- a/src/Maui/Prism.Maui/Controls/PrismNavigationPage.cs
+++ b/src/Maui/Prism.Maui/Controls/PrismNavigationPage.cs
@@ -1,4 +1,4 @@
-using Prism.Common;
+using Prism.Common;
using Prism.Navigation;
using UIModalPresentationStyle = Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific.UIModalPresentationStyle;
@@ -12,10 +12,7 @@ public class PrismNavigationPage : NavigationPage
///
/// Creates a new instance of the
///
- public PrismNavigationPage()
- {
- BackButtonPressed += HandleBackButtonPressed;
- }
+ public PrismNavigationPage() { }
///
/// Creates a new instance of the with a specified at the Root
@@ -23,23 +20,14 @@ public PrismNavigationPage()
///
public PrismNavigationPage(Page page)
: base(page)
- {
- BackButtonPressed += HandleBackButtonPressed;
- }
+ { }
///
- public event EventHandler BackButtonPressed;
-
- ///
- protected override bool OnBackButtonPressed()
- {
- BackButtonPressed.Invoke(this, EventArgs.Empty);
- return false;
- }
-
- private async void HandleBackButtonPressed(object sender, EventArgs args)
+ protected sealed override bool OnBackButtonPressed()
{
- await MvvmHelpers.HandleNavigationPageGoBack(this);
+ var result = RootPage != CurrentPage; //fixes: #3178
+ MvvmHelpers.HandleNavigationPageGoBack(this).ConfigureAwait(false);
+ return result;
}
#if IOS
From 66d6c85887ade2574c5d2a40ea5e5fc21dee86c4 Mon Sep 17 00:00:00 2001
From: Brian Lagunas <835562+brianlagunas@users.noreply.github.com>
Date: Thu, 4 Jul 2024 11:48:14 -0600
Subject: [PATCH 2/6] added unit test
---
.../Fixtures/Navigation/NavigationTests.cs | 57 +++++++++++++++++--
1 file changed, 53 insertions(+), 4 deletions(-)
diff --git a/tests/Maui/Prism.DryIoc.Maui.Tests/Fixtures/Navigation/NavigationTests.cs b/tests/Maui/Prism.DryIoc.Maui.Tests/Fixtures/Navigation/NavigationTests.cs
index 904282884..cee39c5c1 100644
--- a/tests/Maui/Prism.DryIoc.Maui.Tests/Fixtures/Navigation/NavigationTests.cs
+++ b/tests/Maui/Prism.DryIoc.Maui.Tests/Fixtures/Navigation/NavigationTests.cs
@@ -5,8 +5,10 @@
using Prism.DryIoc.Maui.Tests.Mocks.ViewModels;
using Prism.DryIoc.Maui.Tests.Mocks.Views;
using Prism.Navigation.Xaml;
+using Prism.Navigation;
using Prism.Xaml;
using TabbedPage = Microsoft.Maui.Controls.TabbedPage;
+using Microsoft.Maui.LifecycleEvents;
namespace Prism.DryIoc.Maui.Tests.Fixtures.Navigation;
@@ -30,7 +32,7 @@ public void PagesInjectScopedInstanceOfIPageAccessor(string uri)
var rootPage = window.Page;
- if(rootPage is FlyoutPage flyoutPage)
+ if (rootPage is FlyoutPage flyoutPage)
{
TestPage(flyoutPage);
rootPage = flyoutPage.Detail;
@@ -659,6 +661,53 @@ public void Navigate_And_SelectTab(string selectTab, Type viewType)
Assert.IsType(viewType, child);
}
+ [Fact]
+ public async Task Issue3123_GoBack_SendsAppToBackground()
+ {
+ var errorInvoked = false;
+ var mauiApp = CreateBuilder(prism => prism
+ .AddGlobalNavigationObserver(context => context.Subscribe(x =>
+ {
+ //this error message is used in this unit test to know that the SendAppToBackground method was called
+ //for Android we send the app to the background and do not throw the exception, otherwise we throw and quit the app
+ if (!x.Result.Success && x.Result?.Exception?.Message == NavigationException.CannotPopApplicationMainPage)
+ errorInvoked = true;
+ }))
+ .CreateWindow(nav => nav.CreateBuilder()
+ .AddTabbedSegment(page =>
+ page.CreateTab(t =>
+ t.AddNavigationPage()
+ .AddSegment("MockViewA")
+ .AddSegment("MockViewB")))
+ .NavigateAsync()))
+ .Build();
+ var window = GetWindow(mauiApp);
+
+ var tabbedPage = window.Page as TabbedPage;
+ Assert.NotNull(tabbedPage);
+
+ var currentPage = tabbedPage.CurrentPage;
+ Assert.IsType(currentPage);
+ Assert.Equal(2, currentPage.Navigation.NavigationStack.Count);
+
+ var navPage = (PrismNavigationPage)currentPage;
+ Assert.IsType(navPage.CurrentPage);
+
+ var container = navPage.CurrentPage.GetContainerProvider();
+ var navService = container.Resolve();
+ await navService.GoBackAsync();
+
+ Assert.False(errorInvoked);
+ Assert.IsType(navPage.CurrentPage);
+ Assert.Single(currentPage.Navigation.NavigationStack);
+
+ container = navPage.CurrentPage.GetContainerProvider();
+ navService = container.Resolve();
+ await navService.GoBackAsync();
+
+ Assert.True(errorInvoked);
+ }
+
private static void TestPage(Page page, bool ignoreNavigationPage = false)
{
Assert.NotNull(page.BindingContext);
@@ -671,7 +720,7 @@ private static void TestPage(Page page, bool ignoreNavigationPage = false)
Assert.NotNull(accessor.Page);
Assert.Same(page, accessor.Page);
- if(page.Parent is not null)
+ if (page.Parent is not null)
{
Assert.False(page.BindingContext == page);
Assert.False(page.BindingContext == page.Parent);
@@ -690,7 +739,7 @@ private static void TestPage(Page page, bool ignoreNavigationPage = false)
if (page is TabbedPage tabbedPage)
{
- foreach(var child in tabbedPage.Children)
+ foreach (var child in tabbedPage.Children)
{
TestPage(child, tabbedPage is MockExplicitTabbedPage);
@@ -734,7 +783,7 @@ private static void TestPageBehaviors(Page page)
Assert.Equal(expectedBehaviors, page.Behaviors.Count);
- switch(page)
+ switch (page)
{
case TabbedPage:
TestTabbedPageBehaviors(page);
From 975e387694ac93647b7b10b650b3aaf810404878 Mon Sep 17 00:00:00 2001
From: Brian Lagunas <835562+brianlagunas@users.noreply.github.com>
Date: Thu, 4 Jul 2024 16:24:05 -0600
Subject: [PATCH 3/6] fixing navigation scenarios
---
.../MauiModule/ViewModels/ViewModelBase.cs | 7 +++-
e2e/Maui/PrismMauiDemo/MauiProgram.cs | 40 ++++++++++++-------
.../Controls/PrismNavigationPage.cs | 3 +-
.../Navigation/PageNavigationService.cs | 13 +++---
src/Maui/Prism.Maui/Navigation/PrismWindow.cs | 4 +-
src/Maui/Prism.Maui/PrismAppBuilder.cs | 5 ---
6 files changed, 41 insertions(+), 31 deletions(-)
diff --git a/e2e/Maui/MauiModule/ViewModels/ViewModelBase.cs b/e2e/Maui/MauiModule/ViewModels/ViewModelBase.cs
index bd7b03805..9a7efdf1a 100644
--- a/e2e/Maui/MauiModule/ViewModels/ViewModelBase.cs
+++ b/e2e/Maui/MauiModule/ViewModels/ViewModelBase.cs
@@ -3,7 +3,7 @@
namespace MauiModule.ViewModels;
-public abstract class ViewModelBase : BindableBase, IInitialize, INavigatedAware, IPageLifecycleAware
+public abstract class ViewModelBase : BindableBase, IInitialize, INavigatedAware, IPageLifecycleAware, IConfirmNavigation
{
protected INavigationService _navigationService { get; }
protected IPageDialogService _pageDialogs { get; }
@@ -109,4 +109,9 @@ public void OnDisappearing()
{
Messages.Add("View Disappearing");
}
+
+ public virtual bool CanNavigate(INavigationParameters parameters)
+ {
+ return true;
+ }
}
diff --git a/e2e/Maui/PrismMauiDemo/MauiProgram.cs b/e2e/Maui/PrismMauiDemo/MauiProgram.cs
index ca013122a..b50daf1fa 100644
--- a/e2e/Maui/PrismMauiDemo/MauiProgram.cs
+++ b/e2e/Maui/PrismMauiDemo/MauiProgram.cs
@@ -38,21 +38,31 @@ public static MauiApp CreateMauiApp()
if (status == "Failed" && !string.IsNullOrEmpty(x.Result?.Exception?.Message))
Console.Error.WriteLine(x.Result.Exception.Message);
}))
- //.CreateWindow(nav => nav.CreateBuilder()
- // .AddTabbedSegment(page =>
- // page.CreateTab("ViewC")
- // .CreateTab(t =>
- // t.AddNavigationPage()
- // .AddSegment("ViewA", s => s.AddParameter("message", "Hello Tab - ViewA"))
- // .AddSegment("ViewB", s => s.AddParameter("message", "Hello Tab - ViewB")))
- // //.CreateTab("ViewC", s => s.AddParameter("message", "Hello Tab - ViewC"))
- // .SelectedTab("NavigationPage|ViewB"))
- // .AddParameter("message_global", "This is a Global Message")
- // .Navigate())
- //.CreateWindow("ViewA/ViewB/ViewC")
- .CreateWindow(navigationService => navigationService.CreateBuilder()
- .AddSegment()
- .NavigateAsync(HandleNavigationError))
+ //.CreateWindow(nav => nav.CreateBuilder()
+ // .AddTabbedSegment(page =>
+ // page.CreateTab("ViewC")
+ // .CreateTab(t =>
+ // t.AddNavigationPage()
+ // .AddSegment("ViewA", s => s.AddParameter("message", "Hello Tab - ViewA"))
+ // .AddSegment("ViewB", s => s.AddParameter("message", "Hello Tab - ViewB")))
+ // //.CreateTab("ViewC", s => s.AddParameter("message", "Hello Tab - ViewC"))
+ // .SelectedTab("NavigationPage|ViewB"))
+ // .AddParameter("message_global", "This is a Global Message")
+ // .Navigate())
+ //.CreateWindow("ViewA/ViewB") //broken
+ //.CreateWindow("NavigationPage/TabbedPage?createTab=ViewB/ViewC") //works
+ //.CreateWindow("ViewA/NavigationPage/TabbedPage?createTab=ViewB/ViewC") //works
+ //.CreateWindow(navigationService => navigationService.CreateBuilder()
+ // .AddSegment()
+ // .NavigateAsync(HandleNavigationError))
+ .CreateWindow(nav => nav
+ .CreateBuilder()
+ .AddTabbedSegment(page =>
+ page.CreateTab(t =>
+ t.AddNavigationPage()
+ .AddSegment("ViewA")
+ .AddSegment("ViewB")))
+ .NavigateAsync()) //works
)
.ConfigureFonts(fonts =>
{
diff --git a/src/Maui/Prism.Maui/Controls/PrismNavigationPage.cs b/src/Maui/Prism.Maui/Controls/PrismNavigationPage.cs
index 94bbd25b9..a8b8d4ab0 100644
--- a/src/Maui/Prism.Maui/Controls/PrismNavigationPage.cs
+++ b/src/Maui/Prism.Maui/Controls/PrismNavigationPage.cs
@@ -25,9 +25,8 @@ public PrismNavigationPage(Page page)
///
protected sealed override bool OnBackButtonPressed()
{
- var result = RootPage != CurrentPage; //fixes: #3178
MvvmHelpers.HandleNavigationPageGoBack(this).ConfigureAwait(false);
- return result;
+ return true; //Prism will always handle the navigation
}
#if IOS
diff --git a/src/Maui/Prism.Maui/Navigation/PageNavigationService.cs b/src/Maui/Prism.Maui/Navigation/PageNavigationService.cs
index aecc7eb79..8a3cc401c 100644
--- a/src/Maui/Prism.Maui/Navigation/PageNavigationService.cs
+++ b/src/Maui/Prism.Maui/Navigation/PageNavigationService.cs
@@ -2,9 +2,7 @@
using System.Web;
using Prism.Common;
using Prism.Events;
-using Prism.Extensions;
using Prism.Mvvm;
-using Prism.Navigation.Regions;
using Application = Microsoft.Maui.Controls.Application;
using XamlTab = Prism.Navigation.Xaml.TabbedPage;
@@ -100,10 +98,6 @@ private async Task GoBackInternalAsync(INavigationParameters
NavigationSource = PageNavigationSource.NavigationService;
page = GetCurrentPage();
- if (IsRoot(GetPageFromWindow(), page))
- {
- return SendAppToBackground(page);
- }
parameters.GetNavigationParametersInternal().Add(KnownInternalParameters.NavigationMode, NavigationMode.Back);
@@ -113,6 +107,11 @@ private async Task GoBackInternalAsync(INavigationParameters
throw new NavigationException(NavigationException.IConfirmNavigationReturnedFalse, page);
}
+ if (IsRoot(GetPageFromWindow(), page))
+ {
+ return SendAppToBackground(page);
+ }
+
bool useModalForDoPop = UseModalGoBack(page, parameters);
Page previousPage = MvvmHelpers.GetOnNavigatedToTarget(page, Window?.Page, useModalForDoPop);
@@ -1249,6 +1248,8 @@ private bool GoBackModal(NavigationPage navPage)
return true;
else if (navPage.Parent is TabbedPage tabbed && tabbed != rootPage)
return true;
+ else if (rootPage != navPage || IsRoot(rootPage, navPage.CurrentPage))
+ return true;
return false;
}
diff --git a/src/Maui/Prism.Maui/Navigation/PrismWindow.cs b/src/Maui/Prism.Maui/Navigation/PrismWindow.cs
index 83a81fed8..ee4210563 100644
--- a/src/Maui/Prism.Maui/Navigation/PrismWindow.cs
+++ b/src/Maui/Prism.Maui/Navigation/PrismWindow.cs
@@ -84,14 +84,14 @@ public void OnSystemBack()
if (dialogContainer.Dismiss.CanExecute(null))
dialogContainer.Dismiss.Execute(null);
}
- else
+ else if (PageNavigationService.NavigationSource == PageNavigationSource.Device)
{
var navigation = container.Resolve();
navigation.GoBackAsync();
}
}
- private bool IsRoot(Page page)
+ internal bool IsRoot(Page page)
{
if (page == Page) return true;
diff --git a/src/Maui/Prism.Maui/PrismAppBuilder.cs b/src/Maui/Prism.Maui/PrismAppBuilder.cs
index f4a1b7452..ef06115ec 100644
--- a/src/Maui/Prism.Maui/PrismAppBuilder.cs
+++ b/src/Maui/Prism.Maui/PrismAppBuilder.cs
@@ -78,11 +78,6 @@ internal PrismAppBuilder(IContainerExtension containerExtension, MauiAppBuilder
if (window is null)
return false;
- if (window.CurrentPage?.Parent is NavigationPage)
- {
- return true;
- }
-
if(window.IsRootPage)
{
return false;
From 310e48b5191b13fe4cc8790a90c1ace3991a6a15 Mon Sep 17 00:00:00 2001
From: Brian Lagunas <835562+brianlagunas@users.noreply.github.com>
Date: Thu, 4 Jul 2024 16:26:25 -0600
Subject: [PATCH 4/6] fixed test reference
---
.../Maui/Prism.DryIoc.Maui.Tests/Prism.DryIoc.Maui.Tests.csproj | 1 +
1 file changed, 1 insertion(+)
diff --git a/tests/Maui/Prism.DryIoc.Maui.Tests/Prism.DryIoc.Maui.Tests.csproj b/tests/Maui/Prism.DryIoc.Maui.Tests/Prism.DryIoc.Maui.Tests.csproj
index 15d1c2b6c..8e3eaacd0 100644
--- a/tests/Maui/Prism.DryIoc.Maui.Tests/Prism.DryIoc.Maui.Tests.csproj
+++ b/tests/Maui/Prism.DryIoc.Maui.Tests/Prism.DryIoc.Maui.Tests.csproj
@@ -29,6 +29,7 @@
+
From bb6a2c2405c66d58ca1cf5c0548a4d168a8583a0 Mon Sep 17 00:00:00 2001
From: Brian Lagunas <835562+brianlagunas@users.noreply.github.com>
Date: Fri, 5 Jul 2024 13:09:32 -0600
Subject: [PATCH 5/6] added message
---
e2e/Maui/MauiModule/ViewModels/ViewModelBase.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/e2e/Maui/MauiModule/ViewModels/ViewModelBase.cs b/e2e/Maui/MauiModule/ViewModels/ViewModelBase.cs
index 9a7efdf1a..8f1720b9a 100644
--- a/e2e/Maui/MauiModule/ViewModels/ViewModelBase.cs
+++ b/e2e/Maui/MauiModule/ViewModels/ViewModelBase.cs
@@ -112,6 +112,7 @@ public void OnDisappearing()
public virtual bool CanNavigate(INavigationParameters parameters)
{
+ Messages.Add("Can Navigate");
return true;
}
}
From 4d26911c1eeb857617b69195aa7fdccd0cb8bdf3 Mon Sep 17 00:00:00 2001
From: Brian Lagunas <835562+brianlagunas@users.noreply.github.com>
Date: Fri, 5 Jul 2024 13:10:58 -0600
Subject: [PATCH 6/6] changed sample startup nav
---
e2e/Maui/PrismMauiDemo/MauiProgram.cs | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/e2e/Maui/PrismMauiDemo/MauiProgram.cs b/e2e/Maui/PrismMauiDemo/MauiProgram.cs
index b50daf1fa..2c6d0d63c 100644
--- a/e2e/Maui/PrismMauiDemo/MauiProgram.cs
+++ b/e2e/Maui/PrismMauiDemo/MauiProgram.cs
@@ -52,17 +52,17 @@ public static MauiApp CreateMauiApp()
//.CreateWindow("ViewA/ViewB") //broken
//.CreateWindow("NavigationPage/TabbedPage?createTab=ViewB/ViewC") //works
//.CreateWindow("ViewA/NavigationPage/TabbedPage?createTab=ViewB/ViewC") //works
- //.CreateWindow(navigationService => navigationService.CreateBuilder()
- // .AddSegment()
- // .NavigateAsync(HandleNavigationError))
- .CreateWindow(nav => nav
- .CreateBuilder()
- .AddTabbedSegment(page =>
- page.CreateTab(t =>
- t.AddNavigationPage()
- .AddSegment("ViewA")
- .AddSegment("ViewB")))
- .NavigateAsync()) //works
+ //.CreateWindow(nav => nav
+ // .CreateBuilder()
+ // .AddTabbedSegment(page =>
+ // page.CreateTab(t =>
+ // t.AddNavigationPage()
+ // .AddSegment("ViewA")
+ // .AddSegment("ViewB")))
+ // .NavigateAsync()) //works
+ .CreateWindow(navigationService => navigationService.CreateBuilder()
+ .AddSegment()
+ .NavigateAsync(HandleNavigationError))
)
.ConfigureFonts(fonts =>
{