private static async Task OnNavigatingToAsync(Page toPage, INavigationParameters parameters) { PageUtilities.OnNavigatingTo(toPage, parameters); await PageUtilitiesExtended.OnNavigatingToAsync(toPage, parameters); if (toPage is TabbedPage tabbedPage) { if (tabbedPage.CurrentPage is NavigationPage navigationPage) { PageUtilities.OnNavigatingTo(navigationPage.CurrentPage, parameters); await PageUtilitiesExtended.OnNavigatingToAsync(navigationPage.CurrentPage, parameters); } else { PageUtilities.OnNavigatingTo(tabbedPage.CurrentPage, parameters); await PageUtilitiesExtended.OnNavigatingToAsync(tabbedPage.CurrentPage, parameters); } } else if (toPage is CarouselPage carouselPage) { foreach (var child in carouselPage.Children) { PageUtilities.OnNavigatingTo(child, parameters); await PageUtilitiesExtended.OnNavigatingToAsync(child, parameters); } } }
void ConfigureTabbedPage(TabbedPage tabbedPage, string segment) { foreach (var child in tabbedPage.Children) { PageUtilitiesExtended.SetAutowireViewModelOnPage(child); _pageBehaviorFactory.ApplyPageBehaviors(child); if (child is NavigationPage navPage) { PageUtilitiesExtended.SetAutowireViewModelOnPage(navPage.CurrentPage); _pageBehaviorFactory.ApplyPageBehaviors(navPage.CurrentPage); } } var parameters = UriParsingHelper.GetSegmentParameters(segment); var tabsToCreate = parameters.GetValues <string>(KnownNavigationParameters.CreateTab); if (tabsToCreate.Count() > 0) { foreach (var tabToCreate in tabsToCreate) { //created tab can be a single view or a view nested in a NavigationPage with the syntax "NavigationPage|ViewToCreate" var tabSegements = tabToCreate.Split('|'); if (tabSegements.Length > 1) { var navigationPage = CreatePageFromSegment(tabSegements[0]) as NavigationPage; if (navigationPage != null) { var navigationPageChild = CreatePageFromSegment(tabSegements[1]); navigationPage.PushAsync(navigationPageChild); //when creating a NavigationPage w/ DI, a blank Page object is injected into the ctor. Let's remove it if (navigationPage.Navigation.NavigationStack.Count > 1) { navigationPage.Navigation.RemovePage(navigationPage.Navigation.NavigationStack[0]); } //set the title because Xamarin doesn't do this for us. navigationPage.Title = navigationPageChild.Title; navigationPage.Icon = navigationPageChild.Icon; tabbedPage.Children.Add(navigationPage); } } else { var tab = CreatePageFromSegment(tabToCreate); tabbedPage.Children.Add(tab); } } } TabbedPageSelectTab(tabbedPage, parameters); }
void ConfigureCarouselPage(CarouselPage carouselPage, string segment) { foreach (var child in carouselPage.Children) { PageUtilitiesExtended.SetAutowireViewModelOnPage(child); } var parameters = UriParsingHelper.GetSegmentParameters(segment); CarouselPageSelectTab(carouselPage, parameters); }
/// <summary> /// When navigating inside a NavigationPage: Pops all but the root Page off the navigation stack /// </summary> /// <param name="navigationService">The INavigatinService instance</param> /// <param name="parameters">The navigation parameters</param> /// <remarks>Only works when called from a View within a NavigationPage</remarks> protected virtual async Task <INavigationResult> GoBackToRootInternal(INavigationParameters parameters) { var result = new NavigationResult(); try { if (parameters == null) { parameters = new NavigationParameters(); } parameters.GetNavigationParametersInternal().Add(KnownInternalParameters.NavigationMode, NavigationMode.Back); var page = GetCurrentPage(); var canNavigate = await PageUtilities.CanNavigateAsync(page, parameters); if (!canNavigate) { result.Exception = new Exception($"IConfirmNavigation for {page} returned false"); return(result); } List <Page> pagesToDestroy = page.Navigation.NavigationStack.ToList(); // get all pages to destroy pagesToDestroy.Reverse(); // destroy them in reverse order var root = pagesToDestroy.Last(); pagesToDestroy.Remove(root); //don't destroy the root page PageUtilities.OnNavigatingTo(root, parameters); await PageUtilitiesExtended.OnNavigatingToAsync(root, parameters); await page.Navigation.PopToRootAsync(); foreach (var destroyPage in pagesToDestroy) { PageUtilities.OnNavigatedFrom(destroyPage, parameters); PageUtilities.DestroyPage(destroyPage); } PageUtilities.OnNavigatedTo(root, parameters); result.Success = true; return(result); } catch (InvalidOperationException ex) { result.Exception = new Exception("GoBackToRootAsync can only be called when the calling Page is within a NavigationPage.", ex); return(result); } catch (Exception ex) { result.Exception = ex; return(result); } }
/// <summary> /// Navigates to the most recent entry in the back navigation history by popping the calling Page off the navigation stack. /// </summary> /// <param name="parameters">The navigation parameters</param> /// <param name="useModalNavigation">If <c>true</c> uses PopModalAsync, if <c>false</c> uses PopAsync</param> /// <param name="animated">If <c>true</c> the transition is animated, if <c>false</c> there is no animation on transition.</param> /// <returns>If <c>true</c> a go back operation was successful. If <c>false</c> the go back operation failed.</returns> protected virtual async Task <INavigationResult> GoBackInternal(INavigationParameters parameters, bool?useModalNavigation, bool animated) { var result = new NavigationResult(); try { NavigationSource = PageNavigationSource.NavigationService; var page = GetCurrentPage(); var segmentParameters = UriParsingHelper.GetSegmentParameters(null, parameters); segmentParameters.GetNavigationParametersInternal().Add(KnownInternalParameters.NavigationMode, NavigationMode.Back); var canNavigate = await PageUtilities.CanNavigateAsync(page, segmentParameters); if (!canNavigate) { result.Exception = new Exception($"IConfirmNavigation for {page} returned false"); return(result); } bool useModalForDoPop = UseModalNavigation(page, useModalNavigation); Page previousPage = PageUtilities.GetOnNavigatedToTarget(page, _applicationProvider.MainPage, useModalForDoPop); PageUtilities.OnNavigatingTo(previousPage, segmentParameters); await PageUtilitiesExtended.OnNavigatingToAsync(previousPage, segmentParameters); var poppedPage = await DoPop(page.Navigation, useModalForDoPop, animated); if (poppedPage != null) { PageUtilities.OnNavigatedFrom(page, segmentParameters); PageUtilities.OnNavigatedTo(previousPage, segmentParameters); PageUtilities.DestroyPage(poppedPage); result.Success = true; return(result); } } catch (Exception ex) { _logger.Log(ex.ToString(), Category.Exception, Priority.High); result.Exception = ex; return(result); } finally { NavigationSource = PageNavigationSource.Device; } result.Exception = new Exception("Unknown error occured."); return(result); }
protected virtual Task ProcessNavigationForRemovePageSegments(Page currentPage, string nextSegment, Queue <string> segments, INavigationParameters parameters, bool?useModalNavigation, bool animated) { if (!PageUtilitiesExtended.HasDirectNavigationPageParent(currentPage)) { throw new InvalidOperationException("Removing views using the relative '../' syntax while navigating is only supported within a NavigationPage"); } if (CanRemoveAndPush(segments)) { return(RemoveAndPush(currentPage, nextSegment, segments, parameters, useModalNavigation, animated)); } else { return(RemoveAndGoBack(currentPage, nextSegment, segments, parameters, useModalNavigation, animated)); } }
internal static bool UseModalNavigation(Page currentPage, bool?useModalNavigationDefault) { bool useModalNavigation = true; if (useModalNavigationDefault.HasValue) { useModalNavigation = useModalNavigationDefault.Value; } else if (currentPage is NavigationPage) { useModalNavigation = false; } else { useModalNavigation = !PageUtilitiesExtended.HasNavigationPageParent(currentPage); } return(useModalNavigation); }
protected virtual Page CreatePageFromSegment(string segment) { try { var segmentName = UriParsingHelper.GetSegmentName(segment); var page = CreatePage(segmentName); if (page == null) { throw new NullReferenceException(string.Format("{0} could not be created. Please make sure you have registered {0} for navigation.", segmentName)); } PageUtilitiesExtended.SetAutowireViewModelOnPage(page); _pageBehaviorFactory.ApplyPageBehaviors(page); ConfigurePages(page, segment); return(page); } catch (Exception e) { _logger.Log(e.ToString(), Category.Exception, Priority.High); throw; } }
protected virtual async Task UseReverseNavigation(Page currentPage, string nextSegment, Queue <string> segments, INavigationParameters parameters, bool?useModalNavigation, bool animated) { var navigationStack = new Stack <string>(); if (!String.IsNullOrWhiteSpace(nextSegment)) { navigationStack.Push(nextSegment); } var illegalSegments = new Queue <string>(); bool illegalPageFound = false; foreach (var item in segments) { //if we run into an illegal page, we need to create new navigation segments to properly handle the deep link if (illegalPageFound) { illegalSegments.Enqueue(item); continue; } //if any page decide to go modal, we need to consider it and all pages after it an illegal page var pageParameters = UriParsingHelper.GetSegmentParameters(item); if (pageParameters.ContainsKey(KnownNavigationParameters.UseModalNavigation)) { if (pageParameters.GetValue <bool>(KnownNavigationParameters.UseModalNavigation)) { illegalSegments.Enqueue(item); illegalPageFound = true; } else { navigationStack.Push(item); } } else { var pageType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(item)); if (PageUtilitiesExtended.IsSameOrSubclassOf <MasterDetailPage>(pageType)) { illegalSegments.Enqueue(item); illegalPageFound = true; } else { navigationStack.Push(item); } } } var pageOffset = currentPage.Navigation.NavigationStack.Count; if (currentPage.Navigation.NavigationStack.Count > 2) { pageOffset = currentPage.Navigation.NavigationStack.Count - 1; } var onNavigatedFromTarget = currentPage; if (currentPage is NavigationPage navPage && navPage.CurrentPage != null) { onNavigatedFromTarget = navPage.CurrentPage; } bool insertBefore = false; while (navigationStack.Count > 0) { var segment = navigationStack.Pop(); var nextPage = CreatePageFromSegment(segment); await DoNavigateAction(onNavigatedFromTarget, segment, nextPage, parameters, async() => { await DoPush(currentPage, nextPage, useModalNavigation, animated, insertBefore, pageOffset); }); insertBefore = true; } //if an illegal page is found, we force a Modal navigation if (illegalSegments.Count > 0) { await ProcessNavigation(currentPage.Navigation.NavigationStack.Last(), illegalSegments, parameters, true, animated); } }
internal static bool UseReverseNavigation(Page currentPage, Type nextPageType) { return(PageUtilitiesExtended.HasNavigationPageParent(currentPage) && PageUtilitiesExtended.IsSameOrSubclassOf <ContentPage>(nextPageType)); }