diff --git a/src/Maui/Prism.Maui/Navigation/PageNavigationService.cs b/src/Maui/Prism.Maui/Navigation/PageNavigationService.cs index 471fd41c4..da138875f 100644 --- a/src/Maui/Prism.Maui/Navigation/PageNavigationService.cs +++ b/src/Maui/Prism.Maui/Navigation/PageNavigationService.cs @@ -340,22 +340,29 @@ public virtual async Task NavigateFromAsync(string viewName, try { + if (route.IsAbsoluteUri) throw new NavigationException(NavigationException.UnsupportedAbsoluteUri); + parameters ??= new NavigationParameters(); NavigationSource = PageNavigationSource.NavigationService; - var routeSegments = UriParsingHelper.GetUriSegments(route); + var navigationSegments = UriParsingHelper.GetUriSegments(route); // Find a page that matches the viewName. - var page = GetCurrentPage(); - while (page != null) + var currentPage = GetCurrentPage(); + var navigationPages = currentPage.Navigation.NavigationStack.ToList(); + navigationPages.Reverse(); + var foundPage = navigationPages.FirstOrDefault(page => ViewModelLocator.GetNavigationName(page) == viewName); + var removePageCount = navigationPages.IndexOf(foundPage); + + // Insert RemovePageSegment. + var routeString = route.ToString(); + for (int i = 0; i < removePageCount; i++) { - if (page is not null && ViewModelLocator.GetNavigationName(page) == viewName) - break; - page = page.GetParentPage(); + AddToFront(navigationSegments, RemovePageSegment); } - await ProcessNavigation(page, routeSegments, parameters, null, null); + await ProcessNavigation(currentPage, navigationSegments, parameters, null, null); return Notify(route, parameters); } @@ -371,6 +378,23 @@ public virtual async Task NavigateFromAsync(string viewName, } } + private static void AddToFront(Queue queue, T element) + { + var tempQueue = new Queue(); + + while (queue.Count > 0) + { + tempQueue.Enqueue(queue.Dequeue()); + } + + queue.Enqueue(element); + + while (tempQueue.Count > 0) + { + queue.Enqueue(tempQueue.Dequeue()); + } + } + /// /// Selects a Tab of the TabbedPage parent. /// diff --git a/src/Prism.Core/Navigation/NavigationException.cs b/src/Prism.Core/Navigation/NavigationException.cs index 1ffecac4b..1077f64d0 100644 --- a/src/Prism.Core/Navigation/NavigationException.cs +++ b/src/Prism.Core/Navigation/NavigationException.cs @@ -72,6 +72,11 @@ public class NavigationException : Exception /// public const string UnknownException = "An unknown error occurred. You may need to specify whether to Use Modal Navigation or not."; + /// + /// The Message returned when an absolute path is specified but not supported. + /// + public const string UnsupportedAbsoluteUri = "An unsupported absolute uri. Please use a relative URI."; + /// /// Initializes a new instance of the /// 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 70db25cd6..ba5ed8903 100644 --- a/tests/Maui/Prism.DryIoc.Maui.Tests/Fixtures/Navigation/NavigationTests.cs +++ b/tests/Maui/Prism.DryIoc.Maui.Tests/Fixtures/Navigation/NavigationTests.cs @@ -510,29 +510,20 @@ public async Task Navigation_Animation_IsFalse() } [Fact] - public async Task Navigation_FromPageUsingRoute() + public async Task Navigation_FromPageUsingRoute_OnNavigationPage() { - var mauiApp = CreateBuilder(prism => prism.CreateWindow("MockHome/NavigationPage/MockViewA")) + var mauiApp = CreateBuilder(prism => prism.CreateWindow("NavigationPage/MockViewA/MockViewB/MockViewC")) .Build(); var window = GetWindow(mauiApp); + var navigationService = Prism.Navigation.Xaml.Navigation.GetNavigationService(window.CurrentPage); + var currentNavigationStackUri = string.Join("/", window.CurrentPage.Navigation.NavigationStack.Select(v => v.GetType().Name)); + Assert.Equal("MockViewA/MockViewB/MockViewC", currentNavigationStackUri); - var pageNavigatingFrom = (MockHome)window.Page; - var navigationPage = (NavigationPage)pageNavigatingFrom.Detail; - Assert.IsType(navigationPage.CurrentPage); - - var result = await navigationPage.CurrentPage.GetContainerProvider() - .Resolve() - .NavigateFromAsync("MockHome", UriParsingHelper.Parse("NavigationPage/MockViewB"), null); + var result = await navigationService.NavigateFromAsync("MockViewA", UriParsingHelper.Parse("MockViewD/MockViewE"), null); Assert.True(result.Success); - - // MockHome(FlyoutPage) has not been replaced. - var pageNavigatedFrom = (MockHome)window.Page; - Assert.Equal(pageNavigatingFrom, pageNavigatedFrom); - - // Navigation should be succeeded. - navigationPage = (NavigationPage)pageNavigatedFrom.Detail; - Assert.IsType(navigationPage.CurrentPage); + currentNavigationStackUri = string.Join("/", window.CurrentPage.Navigation.NavigationStack.Select(v => v.GetType().Name)); + Assert.Equal("MockViewA/MockViewD/MockViewE", currentNavigationStackUri); } [Fact]