protected virtual async Task ProcessNavigationForNavigationPage(NavigationPage currentPage, string nextSegment, Queue <string> segments, NavigationParameters parameters, bool?useModalNavigation, bool animated) { if (currentPage.Navigation.NavigationStack.Count == 0) { await UseReverseNavigation(currentPage, nextSegment, segments, parameters, false, animated); return; } var clearNavigationStack = GetClearNavigationPageNavigationStack(currentPage); var isEmptyOfNavigationStack = currentPage.Navigation.NavigationStack.Count == 0; List <Page> destroyPages; if (clearNavigationStack && !isEmptyOfNavigationStack) { destroyPages = currentPage.Navigation.NavigationStack.ToList(); destroyPages.Reverse(); await currentPage.Navigation.PopToRootAsync(false); } else { destroyPages = new List <Page>(); } var topPage = currentPage.Navigation.NavigationStack.LastOrDefault(); var nextPageType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(nextSegment)); if (topPage?.GetType() == nextPageType) { if (clearNavigationStack) { destroyPages.Remove(destroyPages.Last()); } await UseReverseNavigation(topPage, null, segments, parameters, false, animated); await DoNavigateAction(topPage, nextSegment, topPage, parameters); } else { await UseReverseNavigation(currentPage, nextSegment, segments, parameters, false, animated); if (clearNavigationStack && !isEmptyOfNavigationStack) { currentPage.Navigation.RemovePage(topPage); } } foreach (var destroyPage in destroyPages) { PageUtilities.DestroyPage(destroyPage); } }
protected virtual async Task ProcessNavigationForNavigationPage(NavigationPage currentPage, string nextSegment, Queue <string> segments, NavigationParameters parameters, bool?useModalNavigation, bool animated) { if (currentPage.Navigation.NavigationStack.Count == 0) { var newRoot = CreatePageFromSegment(nextSegment); await ProcessNavigation(newRoot, segments, parameters, false, animated); await DoNavigateAction(currentPage, nextSegment, newRoot, parameters, async() => { await DoPush(currentPage, newRoot, false, animated); }); return; } var currentNavRoot = currentPage.Navigation.NavigationStack.Last(); var nextPageType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(nextSegment)); if (currentNavRoot.GetType() == nextPageType) { await ProcessNavigation(currentNavRoot, segments, parameters, false, animated); await DoNavigateAction(currentNavRoot, nextSegment, currentNavRoot, parameters); return; } else { bool clearNavStack = GetClearNavigationPageNavigationStack(currentPage); if (clearNavStack) { await currentPage.Navigation.PopToRootAsync(false); } var newRoot = CreatePageFromSegment(nextSegment); await ProcessNavigation(newRoot, segments, parameters, false, animated); await DoNavigateAction(currentNavRoot, nextSegment, newRoot, parameters, async() => { var push = DoPush(currentPage, newRoot, false, animated); if (clearNavStack) { var pageToRemove = currentPage.Navigation.NavigationStack[0]; currentPage.Navigation.RemovePage(pageToRemove); PageUtilities.DestroyPage(pageToRemove); } await push; }); return; } }
public NavigationPath(int index, string originalString, INavigationParameters parameters) { Index = index; _originalString = originalString; // parse name/key Key = originalString.Split('?').First(); // parse query var queryString = originalString.Split('?').Last(); if (queryString != Key) { QueryString = queryString; } // parse parameters if (!string.IsNullOrEmpty(QueryString)) { var query = new WwwFormUrlDecoder(QueryString); foreach (var item in query) { Parameters.Add(item.Name, item.Value); } } // merge parameters if (parameters != null) { foreach (var item in parameters) { Parameters.Add(item.Key, item.Value); } } // get types if (PageNavigationRegistry.TryGetRegistration(Key, out var info)) { Key = info.Key; View = info.View; ViewModel = info.ViewModel; } else { throw new Exception($"Count not find Key:[{Key}]. Use RegisterTypes()/container.RegisterForNavigation<T, T>()."); } }
protected virtual async Task ProcessNavigationForMasterDetailPage(MasterDetailPage currentPage, string nextSegment, Queue<string> segments, NavigationParameters parameters, bool? useModalNavigation, bool animated) { bool isPresented = GetMasterDetailPageIsPresented(currentPage); var detail = currentPage.Detail; if (detail == null) { var newDetail = CreatePageFromSegment(nextSegment); await ProcessNavigation(newDetail, segments, parameters, useModalNavigation, animated); await DoNavigateAction(null, nextSegment, newDetail, parameters, onNavigationActionCompleted: () => { currentPage.IsPresented = isPresented; currentPage.Detail = newDetail; }); return; } if (useModalNavigation.HasValue && useModalNavigation.Value) { var nextPage = CreatePageFromSegment(nextSegment); await ProcessNavigation(nextPage, segments, parameters, useModalNavigation, animated); await DoNavigateAction(currentPage, nextSegment, nextPage, parameters, async () => { currentPage.IsPresented = isPresented; await DoPush(currentPage, nextPage, true, animated); }); return; } var nextSegmentType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(nextSegment)); if (detail.GetType() == nextSegmentType) { await ProcessNavigation(detail, segments, parameters, useModalNavigation, animated); await DoNavigateAction(null, nextSegment, detail, parameters, onNavigationActionCompleted: () => { currentPage.IsPresented = isPresented; }); return; } else { var newDetail = CreatePageFromSegment(nextSegment); await ProcessNavigation(newDetail, segments, parameters, newDetail is NavigationPage ? false : true, animated); await DoNavigateAction(detail, nextSegment, newDetail, parameters, onNavigationActionCompleted: () => { currentPage.IsPresented = isPresented; currentPage.Detail = newDetail; PageUtilities.DestroyPage(detail); }); return; } }
void NavigateToPageFromMasterDetailPage(MasterDetailPage currentPage, string targetSegment, Page targetPage, NavigationParameters parameters) { var detail = currentPage.Detail; var segmentType = PageNavigationRegistry.GetPageType(targetSegment); if (detail.GetType() == segmentType) { return; } OnNavigatedFrom(detail, parameters); currentPage.Detail = targetPage; OnNavigatedTo(targetPage, parameters); }
private static void AddSegmentToStack(Page page, Stack <string> stack) { if (page == null) { return; } var keyInfo = PageNavigationRegistry.GetPageNavigationInfo(page.GetType()); if (keyInfo != null) { stack.Push(keyInfo.Name); } }
private static void CarouselPageSelectTab(CarouselPage carouselPage, INavigationParameters parameters) { var selectedTab = parameters?.GetValue <string>(KnownNavigationParameters.SelectedTab); if (!string.IsNullOrWhiteSpace(selectedTab)) { var selectedTabType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(selectedTab)); foreach (var child in carouselPage.Children) { if (child.GetType() == selectedTabType) { carouselPage.CurrentPage = child; } } } }
async Task ProcessNavigationForNavigationPage(NavigationPage currentPage, string nextSegment, Queue <string> segments, NavigationParameters parameters, bool?useModalNavigation, bool animated) { if (currentPage.Navigation.NavigationStack.Count == 0) { var newRoot = CreatePageFromSegment(nextSegment); await ProcessNavigation(newRoot, segments, parameters, false, animated); await DoNavigateAction(currentPage, nextSegment, newRoot, parameters, async() => { await DoPush(currentPage, newRoot, false, animated); }); return; } var currentNavRoot = currentPage.Navigation.NavigationStack[0]; var nextPageType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(nextSegment)); if (currentNavRoot.GetType() == nextPageType) { if (currentPage.Navigation.NavigationStack.Count > 1) { await currentPage.Navigation.PopToRootAsync(false); } await ProcessNavigation(currentNavRoot, segments, parameters, false, animated); await DoNavigateAction(currentNavRoot, nextSegment, currentNavRoot, parameters); return; } else { await currentPage.Navigation.PopToRootAsync(false); var newRoot = CreatePageFromSegment(nextSegment); await ProcessNavigation(newRoot, segments, parameters, false, animated); await DoNavigateAction(currentNavRoot, nextSegment, newRoot, parameters, async() => { await DoPush(currentPage, newRoot, false, animated); currentPage.Navigation.RemovePage(currentNavRoot); }); return; } }
void ConfigureCarouselPage(CarouselPage carouselPage, string segment) { var selectedTab = UriParsingHelper.GetSegmentParameters(segment).GetValue <string>(KnownNavigationParameters.SelectedTab); if (!string.IsNullOrWhiteSpace(selectedTab)) { var selectedTabType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(selectedTab)); foreach (var child in carouselPage.Children) { SetAutowireViewModelOnPage(child); if (child.GetType() == selectedTabType) { carouselPage.CurrentPage = child; } } } }
async Task ProcessNavigationForMasterDetailPage(MasterDetailPage currentPage, string nextSegment, Queue <string> segments, NavigationParameters parameters, bool?useModalNavigation, bool animated) { var detail = currentPage.Detail; if (detail == null) { var newDetail = CreatePageFromSegment(nextSegment); await ProcessNavigation(newDetail, segments, parameters, newDetail is NavigationPage?false : true, animated); await DoNavigateAction(null, nextSegment, newDetail, parameters, () => { currentPage.Detail = newDetail; currentPage.IsPresented = false; }); return; } var nextSegmentType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(nextSegment)); if (detail.GetType() == nextSegmentType) { await ProcessNavigation(detail, segments, parameters, useModalNavigation, animated); await DoNavigateAction(null, nextSegment, detail, parameters, () => { currentPage.IsPresented = false; }); return; } else { var newDetail = CreatePageFromSegment(nextSegment); await ProcessNavigation(newDetail, segments, parameters, newDetail is NavigationPage?false : true, animated); await DoNavigateAction(detail, nextSegment, newDetail, parameters, () => { currentPage.Detail = newDetail; currentPage.IsPresented = false; }); return; } }
protected virtual async Task ProcessNavigationForContentPage(Page currentPage, string nextSegment, Queue <string> segments, INavigationParameters parameters, bool?useModalNavigation, bool animated) { var nextPageType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(nextSegment)); bool useReverse = UseReverseNavigation(currentPage, nextPageType) && !(useModalNavigation.HasValue && useModalNavigation.Value); if (!useReverse) { var nextPage = CreatePageFromSegment(nextSegment); await ProcessNavigation(nextPage, segments, parameters, useModalNavigation, animated); await DoNavigateAction(currentPage, nextSegment, nextPage, parameters, async() => { await DoPush(currentPage, nextPage, useModalNavigation, animated); }); } else { await UseReverseNavigation(currentPage, nextSegment, segments, parameters, useModalNavigation, animated); } }
void ProcessNavigationForNavigationPage(Page currentPage, string targetSegment, NavigationPage targetPage, Queue <string> segments, NavigationParameters parameters, bool useModalNavigation, bool animated) { if (targetPage.Navigation.NavigationStack.Count == 0) { ProcessNavigationSegments(targetPage, segments, parameters, false, animated); DoNavigate(currentPage, targetSegment, targetPage, parameters, useModalNavigation, animated); return; } if (segments.Count > 0) // we have a next page { var currentNavRoot = targetPage.Navigation.NavigationStack[0]; var nextPageType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(segments.Peek())); if (currentNavRoot.GetType() == nextPageType) { if (targetPage.Navigation.NavigationStack.Count > 1) { targetPage.Navigation.PopToRootAsync(false); } segments.Dequeue(); ProcessNavigationSegments(currentNavRoot, segments, parameters, false, animated); DoNavigate(currentPage, targetSegment, targetPage, parameters, useModalNavigation, animated); return; } else { targetPage.Navigation.PopToRootAsync(false); ProcessNavigationSegments(targetPage, segments, parameters, false, animated); DoNavigate(currentPage, targetSegment, targetPage, parameters, useModalNavigation, animated); targetPage.Navigation.RemovePage(currentNavRoot); return; } } ProcessNavigationSegments(targetPage, segments, parameters, useModalNavigation, animated); DoNavigate(currentPage, targetSegment, targetPage, parameters, useModalNavigation, animated); }
protected virtual async Task ProcessNavigationForCarouselPage(CarouselPage currentPage, string nextSegment, Queue<string> segments, NavigationParameters parameters, bool? useModalNavigation, bool animated) { var nextSegmentType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(nextSegment)); foreach (var child in currentPage.Children) { if (child.GetType() != nextSegmentType) continue; await ProcessNavigation(child, segments, parameters, useModalNavigation, animated); await DoNavigateAction(null, nextSegment, child, parameters, onNavigationActionCompleted: () => { currentPage.CurrentPage = child; }); return; } var nextPage = CreatePageFromSegment(nextSegment); await ProcessNavigation(nextPage, segments, parameters, useModalNavigation, animated); await DoNavigateAction(currentPage, nextSegment, nextPage, parameters, async () => { await DoPush(currentPage, nextPage, useModalNavigation, animated); }); }
//TODO: this is the exact same code as TabbedPage, how can I use this same method for both page types? void ProcessNavigationForCarouselPage(Page currentPage, string targetSegment, CarouselPage targetPage, Queue <string> segments, NavigationParameters parameters, bool useModalNavigation, bool animated) { if (segments.Count > 0) // we have a next page { var nextSegmentType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(segments.Peek())); foreach (var child in targetPage.Children) { if (child.GetType() != nextSegmentType) { continue; } segments.Dequeue(); ProcessNavigationSegments(child, segments, parameters, useModalNavigation, animated); targetPage.CurrentPage = child; DoNavigate(currentPage, targetSegment, targetPage, parameters, useModalNavigation, animated); return; } } ProcessNavigationSegments(targetPage, segments, parameters, useModalNavigation, animated); DoNavigate(currentPage, targetSegment, targetPage, parameters, useModalNavigation, animated); }
void ConfigureTabbedPage(TabbedPage tabbedPage, string segment) { var selectedTab = UriParsingHelper.GetSegmentParameters(segment).GetValue <string>(KnownNavigationParameters.SelectedTab); if (!string.IsNullOrWhiteSpace(selectedTab)) { //selected tab can be a single view or a view nested in a navigationpage with the syntax "NavigationPage|View" var selectedTabSegements = new Queue <string>(selectedTab.Split('|')); var selectedTabType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(selectedTabSegements.Dequeue())); string selectedTabChildSegment = string.Empty; if (selectedTabSegements.Count > 0) { selectedTabChildSegment = selectedTabSegements.Dequeue(); } foreach (var child in tabbedPage.Children) { if (child.GetType() != selectedTabType) { continue; } if (child is NavigationPage) { var childTabType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(selectedTabChildSegment)); if (((NavigationPage)child).CurrentPage.GetType() != childTabType) { continue; } } tabbedPage.CurrentPage = child; break; } } }
void ProcessNavigationForMasterDetailPage(Page currentPage, string targetSegment, MasterDetailPage targetPage, Queue <string> segments, NavigationParameters parameters, bool useModalNavigation, bool animated) { var detail = targetPage.Detail; if (detail == null) { var newDetail = CreatePage(segments.Dequeue()); ProcessNavigationSegments(newDetail, segments, parameters, newDetail is NavigationPage ? false : true, animated); targetPage.Detail = newDetail; DoNavigate(currentPage, targetSegment, targetPage, parameters, useModalNavigation, animated); return; } if (segments.Count > 0) // we have a next page { var nextSegmentType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(segments.Peek())); if (detail.GetType() == nextSegmentType) { segments.Dequeue(); ProcessNavigationSegments(detail, segments, parameters, useModalNavigation, animated); DoNavigate(currentPage, targetSegment, targetPage, parameters, useModalNavigation, animated); return; } else { var newDetail = CreatePage(segments.Dequeue()); ProcessNavigationSegments(newDetail, segments, parameters, newDetail is NavigationPage ? false : true, animated); targetPage.Detail = newDetail; DoNavigate(currentPage, targetSegment, targetPage, parameters, useModalNavigation, animated); return; } } ProcessNavigationSegments(targetPage, segments, parameters, useModalNavigation, animated); DoNavigate(currentPage, targetSegment, targetPage, parameters, useModalNavigation, animated); }
protected virtual async Task ProcessNavigationForMasterDetailPage(MasterDetailPage currentPage, string nextSegment, Queue <string> segments, INavigationParameters parameters, bool?useModalNavigation, bool animated) { bool isPresented = GetMasterDetailPageIsPresented(currentPage); var detail = currentPage.Detail; if (detail == null) { var newDetail = CreatePageFromSegment(nextSegment); await ProcessNavigation(newDetail, segments, parameters, useModalNavigation, animated); await DoNavigateAction(null, nextSegment, newDetail, parameters, onNavigationActionCompleted : () => { currentPage.IsPresented = isPresented; currentPage.Detail = newDetail; }); return; } if (useModalNavigation.HasValue && useModalNavigation.Value) { var nextPage = CreatePageFromSegment(nextSegment); await ProcessNavigation(nextPage, segments, parameters, useModalNavigation, animated); await DoNavigateAction(currentPage, nextSegment, nextPage, parameters, async() => { currentPage.IsPresented = isPresented; await DoPush(currentPage, nextPage, true, animated); }); return; } var nextSegmentType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(nextSegment)); //we must recreate the NavigationPage everytime or the transitions on iOS will not work properly, unless we meet the two scenarios below bool detailIsNavPage = false; bool reuseNavPage = false; if (detail is NavigationPage navPage) { detailIsNavPage = true; //first we check to see if we are being forced to reuse the NavPage by checking the interface reuseNavPage = !GetClearNavigationPageNavigationStack(navPage); if (!reuseNavPage) { //if we weren't forced to reuse the NavPage, then let's check the NavPage.CurrentPage against the next segment type as we don't want to recreate the entire nav stack //just in case the user is trying to navigate to the same page which may be nested in a NavPage var nextPageType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(segments.Peek())); var currentPageType = navPage.CurrentPage.GetType(); if (nextPageType == currentPageType) { reuseNavPage = true; } } } if ((detailIsNavPage && reuseNavPage) || (!detailIsNavPage && detail.GetType() == nextSegmentType)) { await ProcessNavigation(detail, segments, parameters, useModalNavigation, animated); await DoNavigateAction(null, nextSegment, detail, parameters, onNavigationActionCompleted : () => { currentPage.IsPresented = isPresented; }); return; } else { var newDetail = CreatePageFromSegment(nextSegment); await ProcessNavigation(newDetail, segments, parameters, newDetail is NavigationPage?false : true, animated); await DoNavigateAction(detail, nextSegment, newDetail, parameters, onNavigationActionCompleted : () => { currentPage.IsPresented = isPresented; currentPage.Detail = newDetail; PageUtilities.DestroyPage(detail); }); return; } }
void ConfigureTabbedPage(TabbedPage tabbedPage, string segment) { foreach (var child in tabbedPage.Children) { PageUtilities.SetAutowireViewModelOnPage(child); _pageBehaviorFactory.ApplyPageBehaviors(child); if (child is NavigationPage navPage) { PageUtilities.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); } } } var selectedTab = parameters.GetValue <string>(KnownNavigationParameters.SelectedTab); if (!string.IsNullOrWhiteSpace(selectedTab)) { var selectedTabType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(selectedTab)); var childFound = false; foreach (var child in tabbedPage.Children) { if (!childFound && child.GetType() == selectedTabType) { tabbedPage.CurrentPage = child; childFound = true; } if (child is NavigationPage) { if (!childFound && ((NavigationPage)child).CurrentPage.GetType() == selectedTabType) { tabbedPage.CurrentPage = child; childFound = true; } } } } }
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 (PageUtilities.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); } }
protected virtual async Task UseReverseNavigation(Page currentPage, string nextSegment, Queue <string> segments, NavigationParameters parameters, bool?useModalNavigation, bool animated) { if (String.IsNullOrWhiteSpace(nextSegment)) { return; } var navigationStack = new Stack <string>(); var nextSegmentPageType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(nextSegment)); if (IsSameOrSubclassOf <TabbedPage>(nextSegmentPageType)) { var tabbedPage = (TabbedPage)CreatePageFromSegment(nextSegment); if (segments.Count > 0) { nextSegment = segments.Dequeue(); nextSegmentPageType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(nextSegment)); foreach (var child in tabbedPage.Children) { if (child.GetType() != nextSegmentPageType) { continue; } tabbedPage.CurrentPage = child; } } await DoNavigateAction(currentPage, nextSegment, tabbedPage, parameters, async() => { await DoPush(currentPage, tabbedPage, useModalNavigation, animated, false); }); currentPage = tabbedPage; } else { 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; } var pageType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(item)); if (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; } bool insertBefore = false; while (navigationStack.Count > 0) { Page nextPage = null; var segment = navigationStack.Pop(); if (navigationStack.Count > 0) { //since we are building the stack backwards, check next segment to see if it's a tabbedpage var peekSegment = navigationStack.Peek(); var peekSegmentType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(peekSegment)); //if we have a TabbedPage we must see if the prior segment is a child so we can select the tab if (IsSameOrSubclassOf <TabbedPage>(peekSegmentType)) { var tabbedPageSegment = navigationStack.Pop(); var tabbedPage = (TabbedPage)CreatePageFromSegment(tabbedPageSegment); var childPageType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(segment)); foreach (var child in tabbedPage.Children) { if (child.GetType() != childPageType) { continue; } await DoNavigateAction(null, segment, child, parameters, onNavigationActionCompleted : () => { tabbedPage.CurrentPage = child; }); } nextPage = tabbedPage; } } if (nextPage == null) { nextPage = CreatePageFromSegment(segment); } await DoNavigateAction(currentPage, 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); } }