diff --git a/src/Controls/src/Core/Page.cs b/src/Controls/src/Core/Page.cs index efc893220fbd..028269540b4a 100644 --- a/src/Controls/src/Core/Page.cs +++ b/src/Controls/src/Core/Page.cs @@ -470,7 +470,7 @@ public void SendAppearing() // Visual Hierarchy // The window/application will take care of re-firing this appearing // if it needs to - var window = this.FindParentOfType(); + var window = this.FindParentOfType(); if (window?.Parent == null) { return; diff --git a/src/Controls/src/Core/Shell/Shell.cs b/src/Controls/src/Core/Shell/Shell.cs index 6305472994b9..61ca8df5312f 100644 --- a/src/Controls/src/Core/Shell/Shell.cs +++ b/src/Controls/src/Core/Shell/Shell.cs @@ -1693,7 +1693,14 @@ protected override async Task OnPushModal(Page modal, bool animated) modal.Parent = (Element)_shell.FindParentOfType(); if (!_shell.CurrentItem.CurrentItem.IsPushingModalStack) + { + if (ModalStack.Count > 0) + { + ModalStack[ModalStack.Count - 1].SendDisappearing(); + } + modal.SendAppearing(); + } await base.OnPushModal(modal, animated); diff --git a/src/Controls/src/Core/Shell/ShellSection.cs b/src/Controls/src/Core/Shell/ShellSection.cs index 432b29326b70..292d1604969f 100644 --- a/src/Controls/src/Core/Shell/ShellSection.cs +++ b/src/Controls/src/Core/Shell/ShellSection.cs @@ -408,6 +408,11 @@ async Task PrepareCurrentStackForBeingReplaced(ShellNavigationRequest request, S continue; } + // This is the page that we will eventually get to once we've finished + // modifying the existing navigation stack + // So we want to fire appearing on it + navPage.SendAppearing(); + IsPoppingModalStack = true; while (navStack.Count > popCount && Navigation.ModalStack.Count > 0) diff --git a/src/Controls/tests/Core.UnitTests/ShellLifeCycleTests.cs b/src/Controls/tests/Core.UnitTests/ShellLifeCycleTests.cs index 1ceb0d1897d7..1a0fe9d71831 100644 --- a/src/Controls/tests/Core.UnitTests/ShellLifeCycleTests.cs +++ b/src/Controls/tests/Core.UnitTests/ShellLifeCycleTests.cs @@ -318,7 +318,6 @@ public void AppearingOnShellItemChanged() Assert.False(state.ContentAppearing); } - [Fact] public async Task ShellPartWithModalPush() { @@ -336,7 +335,6 @@ public async Task ShellPartWithModalPush() lifeCycleState.AllTrue(); } - [Fact] public async Task ShellPartWithPagePush() { diff --git a/src/Controls/tests/Core.UnitTests/ShellModalTests.cs b/src/Controls/tests/Core.UnitTests/ShellModalTests.cs index 957d0296bfde..60f3c443abc8 100644 --- a/src/Controls/tests/Core.UnitTests/ShellModalTests.cs +++ b/src/Controls/tests/Core.UnitTests/ShellModalTests.cs @@ -12,6 +12,50 @@ namespace Microsoft.Maui.Controls.Core.UnitTests public class ShellModalTests : ShellTestBase { + [Fact] + public async Task AppearingAndDisappearingFireOnMultipleModals() + { + var windowPage = new ContentPage(); + var modalPage1 = new ContentPage(); + var modalPage2 = new ContentPage(); + + int modal1Appearing = 0; + int modal1Disappearing = 0; + int modal2Appearing = 0; + int modal2Disappearing = 0; + int windowAppearing = 0; + int windowDisappearing = 0; + + modalPage1.Appearing += (_, _) => modal1Appearing++; + modalPage1.Disappearing += (_, _) => modal1Disappearing++; + + modalPage2.Appearing += (_, _) => modal2Appearing++; + modalPage2.Disappearing += (_, _) => modal2Disappearing++; + + windowPage.Appearing += (_, _) => windowAppearing++; + windowPage.Disappearing += (_, _) => windowDisappearing++; + + var window = new TestWindow(new TestShell() { CurrentItem = windowPage }); + await windowPage.Navigation.PushModalAsync(modalPage1); + Assert.Equal(1, modal1Appearing); + + await windowPage.Navigation.PushModalAsync(modalPage2); + Assert.Equal(1, modal2Appearing); + Assert.Equal(1, modal1Disappearing); + + await windowPage.Navigation.PopModalAsync(); + await windowPage.Navigation.PopModalAsync(); + + Assert.Equal(2, modal1Appearing); + Assert.Equal(2, modal1Disappearing); + + Assert.Equal(1, modal2Appearing); + Assert.Equal(1, modal2Disappearing); + + Assert.Equal(2, windowAppearing); + Assert.Equal(1, windowDisappearing); + } + [Fact] public async Task BasicModalBehaviorTest() {