Exemple #1
0
        public void DestroyContentPage()
        {
            var recorder  = new PageNavigationEventRecorder();
            var page      = new ContentPageMock(recorder);
            var viewModel = (ViewModelBase)page.BindingContext;

            PageUtilities.DestroyPage(page);

            Assert.Equal(2, recorder.Records.Count);

            Assert.Equal(page, recorder.Records[0].Sender);
            Assert.Null(page.BindingContext);
            Assert.Equal(0, page.Behaviors.Count);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[0].Event);

            Assert.Equal(viewModel, recorder.Records[1].Sender);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[1].Event);
        }
Exemple #2
0
        /// <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>
        public virtual async Task <bool> GoBackAsync(NavigationParameters parameters = null, bool?useModalNavigation = null, bool animated = true)
        {
            try
            {
                NavigationSource = PageNavigationSource.NavigationService;

                var page = GetCurrentPage();
                var segmentParameters = UriParsingHelper.GetSegmentParameters(null, parameters);
                segmentParameters.Add(KnownNavigationParameters.NavigationMode, NavigationMode.Back);

                var canNavigate = await PageUtilities.CanNavigateAsync(page, segmentParameters);

                if (!canNavigate)
                {
                    return(false);
                }

                bool useModalForDoPop = UseModalNavigation(page, useModalNavigation);
                Page previousPage     = PageUtilities.GetOnNavigatedToTarget(page, _applicationProvider.MainPage, useModalForDoPop);

                PageUtilities.OnNavigatingTo(previousPage, segmentParameters);

                var poppedPage = await DoPop(page.Navigation, useModalForDoPop, animated);

                if (poppedPage != null)
                {
                    PageUtilities.OnNavigatedFrom(page, segmentParameters);
                    PageUtilities.OnNavigatedTo(previousPage, segmentParameters);
                    PageUtilities.DestroyPage(poppedPage);
                    return(true);
                }
            }
            catch (Exception e)
            {
                _logger.Log(e.ToString(), Category.Exception, Priority.High);
                return(false);
            }
            finally
            {
                NavigationSource = PageNavigationSource.Device;
            }

            return(false);
        }
Exemple #3
0
        public void DestroyNavigationPage()
        {
            var recorder                = new PageNavigationEventRecorder();
            var navigationPage          = new NavigationPageMock(recorder);
            var navigationPageViewModel = navigationPage.BindingContext;
            var contentPage1            = navigationPage.CurrentPage;
            var contentPage1ViewModel   = contentPage1.BindingContext;
            var contentPage2            = new ContentPageMock(recorder);
            var contentPage2ViewModel   = contentPage2.BindingContext;

            contentPage1.Navigation.PushAsync(contentPage2);

            PageUtilities.DestroyPage(navigationPage);

            Assert.Equal(6, recorder.Records.Count);

            // contentPage2
            Assert.Equal(contentPage2, recorder.Records[0].Sender);
            Assert.Null(contentPage2.BindingContext);
            Assert.Equal(0, contentPage2.Behaviors.Count);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[0].Event);

            Assert.Equal(contentPage2ViewModel, recorder.Records[1].Sender);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[1].Event);

            // contentPage1
            Assert.Equal(contentPage1, recorder.Records[2].Sender);
            Assert.Null(contentPage1.BindingContext);
            Assert.Equal(0, contentPage1.Behaviors.Count);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[2].Event);

            Assert.Equal(contentPage1ViewModel, recorder.Records[3].Sender);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[3].Event);

            // navigationPage
            Assert.Equal(navigationPage, recorder.Records[4].Sender);
            Assert.Null(navigationPage.BindingContext);
            Assert.Equal(0, navigationPage.Behaviors.Count);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[4].Event);

            Assert.Equal(navigationPageViewModel, recorder.Records[5].Sender);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[5].Event);
        }
        public override async Task <bool> GoBackAsync(INavigationParameters parameters = null, bool?useModalNavigation = default(bool?), bool animated = true)
        {
            try
            {
                NavigationSource = PageNavigationSource.NavigationService;

                switch (PopupUtilities.TopPage(_popupNavigation, _applicationProvider))
                {
                case PopupPage popupPage:
                    var segmentParameters = UriParsingHelper.GetSegmentParameters(null, parameters);
                    segmentParameters.Add(KnownNavigationParameters.NavigationMode, NavigationMode.Back);
                    var previousPage = PopupUtilities.GetOnNavigatedToTarget(_popupNavigation, _applicationProvider);

                    PageUtilities.OnNavigatingTo(previousPage, segmentParameters);
                    await DoPop(popupPage.Navigation, false, animated);

                    if (popupPage != null)
                    {
                        PageUtilities.InvokeViewAndViewModelAction <IActiveAware>(popupPage, a => a.IsActive = false);
                        PageUtilities.OnNavigatedFrom(popupPage, segmentParameters);
                        PageUtilities.OnNavigatedTo(previousPage, segmentParameters);
                        PageUtilities.InvokeViewAndViewModelAction <IActiveAware>(previousPage, a => a.IsActive = true);
                        PageUtilities.DestroyPage(popupPage);
                        return(true);
                    }
                    break;

                default:
                    return(await base.GoBackAsync(parameters, useModalNavigation, animated));
                }
            }
            catch (Exception e)
            {
                _logger.Log(e.ToString(), Category.Exception, Priority.High);
                return(false);
            }
            finally
            {
                NavigationSource = PageNavigationSource.Device;
            }

            return(false);
        }
Exemple #5
0
        public void DestroyCarouselPage()
        {
            var recorder              = new PageNavigationEventRecorder();
            var carouselPage          = new CarouselPageMock(recorder);
            var carouselPageViewModel = carouselPage.BindingContext;
            var childPage2            = carouselPage.Children[1];
            var childPage2ViewModel   = childPage2.BindingContext;

            PageUtilities.DestroyPage(carouselPage);

            Assert.Equal(6, recorder.Records.Count);

            // childPage3 : This page is ContentPage.
            Assert.Equal(carouselPageViewModel, recorder.Records[0].Sender);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[0].Event);

            // childPage2
            Assert.Equal(childPage2, recorder.Records[1].Sender);
            Assert.Null(childPage2.BindingContext);
            Assert.Equal(0, childPage2.Behaviors.Count);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[1].Event);

            Assert.Equal(childPage2ViewModel, recorder.Records[2].Sender);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[2].Event);

            // childPage1 : This page is ContentPage.
            Assert.Equal(carouselPageViewModel, recorder.Records[3].Sender);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[3].Event);

            // tabbedPage
            Assert.Equal(carouselPage, recorder.Records[4].Sender);
            Assert.Null(carouselPage.BindingContext);
            Assert.Equal(0, carouselPage.Behaviors.Count);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[4].Event);

            Assert.Equal(carouselPageViewModel, recorder.Records[5].Sender);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[5].Event);
        }
Exemple #6
0
        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;
            }
        }
Exemple #7
0
        protected virtual async Task ProcessNavigationForNavigationPage(NavigationPage currentPage, string nextSegment, Queue <string> segments, INavigationParameters 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());
                }

                if (segments.Count > 0)
                {
                    await UseReverseNavigation(topPage, segments.Dequeue(), segments, parameters, false, animated);
                }

                await DoNavigateAction(topPage, nextSegment, topPage, parameters, onNavigationActionCompleted : () =>
                {
                    if (nextSegment.Contains(KnownNavigationParameters.SelectedTab))
                    {
                        var segmentParams = UriParsingHelper.GetSegmentParameters(nextSegment);
                        SelectPageTab(topPage, segmentParams);
                    }
                });
            }
            else
            {
                await UseReverseNavigation(currentPage, nextSegment, segments, parameters, false, animated);

                if (clearNavigationStack && !isEmptyOfNavigationStack)
                {
                    currentPage.Navigation.RemovePage(topPage);
                }
            }

            foreach (var destroyPage in destroyPages)
            {
                PageUtilities.DestroyPage(destroyPage);
            }
        }
        public void DestroyTabbedPage()
        {
            var recorder            = new PageNavigationEventRecorder();
            var tabbedPage          = new TabbedPageMock(recorder);
            var tabbedPageViewModel = tabbedPage.BindingContext;
            var tab1               = tabbedPage.Children[0];
            var tab1ViewModel      = tab1.BindingContext;
            var tab2               = tabbedPage.Children[1];
            var tab2ViewModel      = tab2.BindingContext;
            var tab3               = tabbedPage.Children[2];
            var tab3ViewModel      = tab3.BindingContext;
            var tab4               = tabbedPage.Children[3];
            var tab4Child          = ((NavigationPage)tab4).CurrentPage;
            var tab4ViewModel      = tab4.BindingContext;
            var tab4ChildViewModel = tab4Child.BindingContext;
            var tab5               = tabbedPage.Children[4];
            var tab5Child          = ((NavigationPage)tab5).CurrentPage;
            var tab5ViewModel      = tab5.BindingContext;
            var tab5ChildViewModel = tab5Child.BindingContext;


            PageUtilities.DestroyPage(tabbedPage);

            Assert.Equal(13, recorder.Records.Count);

            //tab 5
            Assert.Equal(tab5ViewModel, recorder.Records[0].Sender);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[0].Event);

            Assert.Equal(tab5, recorder.Records[1].Sender);
            Assert.Equal(0, tab5.Behaviors.Count);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[1].Event);

            Assert.Equal(tab5ChildViewModel, recorder.Records[2].Sender);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[2].Event);

            //tab 4
            Assert.Equal(tab4Child, recorder.Records[3].Sender);
            Assert.Equal(0, tab4Child.Behaviors.Count);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[3].Event);

            Assert.Equal(tab4ChildViewModel, recorder.Records[4].Sender);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[4].Event);

            Assert.Equal(tab4, recorder.Records[5].Sender);
            Assert.Equal(0, tab4.Behaviors.Count);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[5].Event);

            Assert.Equal(tab4ViewModel, recorder.Records[6].Sender);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[6].Event);

            //tab 3
            Assert.Equal(tab3, recorder.Records[7].Sender);
            Assert.Null(tab3.BindingContext);
            Assert.Equal(0, tab3.Behaviors.Count);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[7].Event);

            Assert.Equal(tab3ViewModel, recorder.Records[8].Sender);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[8].Event);

            //tab 2 : PageMock has no binding context so it has no entries.

            //tab 1
            Assert.Equal(tab1, recorder.Records[9].Sender);
            Assert.Null(tab1.BindingContext);
            Assert.Equal(0, tab1.Behaviors.Count);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[9].Event);

            Assert.Equal(tab1ViewModel, recorder.Records[10].Sender);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[10].Event);

            //TabbedPage
            Assert.Equal(tabbedPage, recorder.Records[11].Sender);
            Assert.Null(tabbedPage.BindingContext);
            Assert.Equal(0, tabbedPage.Behaviors.Count);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[11].Event);

            Assert.Equal(tabbedPageViewModel, recorder.Records[12].Sender);
            Assert.Equal(PageNavigationEvent.Destroy, recorder.Records[12].Event);
        }
Exemple #9
0
        public static async Task <INavigationResult> GoBackToTargetInternal <T>(INavigationParameters parameters)
        {
            _logger?.Log();
            var result = new NavigationResult();

            try
            {
                if (parameters == null)
                {
                    parameters = new NavigationParameters();
                }

                ((INavigationParametersInternal)parameters).Add("__NavigationMode", NavigationMode.Back); // __NavigationMode is hardcode of Prism.Navigation.KnownInternalParameters.NavigationMode

                var currentPage = PageUtilities.GetCurrentPage(Application.Current.MainPage);

                NavigationPage navigationPage = null;
                var            tmp            = currentPage;
                while (tmp.Parent != null)
                {
                    if (tmp.Parent is NavigationPage)
                    {
                        navigationPage = tmp.Parent as NavigationPage;
                        break;
                    }
                    else
                    {
                        tmp = tmp.Parent as Page;
                    }
                }

                if (navigationPage == null)
                {
                    result.Exception = new NavigationException("Require NavigationPage", currentPage);
                    return(result);
                }

                var canNavigate = await PageUtilities.CanNavigateAsync(currentPage, parameters);

                if (!canNavigate)
                {
                    result.Exception = new NavigationException(NavigationException.IConfirmNavigationReturnedFalse, currentPage);
                    return(result);
                }

                // Cache the stack to avoid mutation.
                var  stack = currentPage.Navigation.NavigationStack.ToList();
                Page root  = navigationPage.RootPage; // Initial root value.

                var pagesToDestroy = new List <Page>();

                // For stack, A > B > C > D. We want to navigate from D to B.
                // A > B > D.
                // The remove order is D > C.
                for (int i = stack.Count - 1; i >= 1; i--) // i = 0 is root page. we don't remove it.
                {
                    var page = stack[i];
                    if (page.BindingContext.GetType() == typeof(T)) // Assume target key is ViewModel's name.
                    {
                        root = page;                                // Root is B.
                        break;
                    }
                    pagesToDestroy.Add(page);
                }

                // Temporary remove prism navigation aware
                var systemGoBackBehavior = navigationPage.Behaviors.FirstOrDefault(p => p is NavigationPageSystemGoBackBehavior);
                if (systemGoBackBehavior != null)
                {
                    navigationPage.Behaviors.Remove(systemGoBackBehavior);
                }

                for (int i = 1; i < pagesToDestroy.Count; i++) // Skip page D, remove page C,
                {
                    currentPage.Navigation.RemovePage(pagesToDestroy[i]);
                }

                await currentPage.Navigation.PopAsync();    // Navigate from D to B.

                foreach (var destroyPage in pagesToDestroy) // D, C OnNavigatedFrom and Destroy
                {
                    PageUtilities.OnNavigatedFrom(destroyPage, parameters);
                    PageUtilities.DestroyPage(destroyPage);
                }
                PageUtilities.OnNavigatedTo(root, parameters); // B OnNavigatedTo

                // Re-add prism navigation aware
                if (systemGoBackBehavior != null)
                {
                    navigationPage.Behaviors.Add(systemGoBackBehavior);
                }

                result.Success = true;
                return(result);
            }
            catch (Exception ex)
            {
                result.Exception = ex;
                return(result);
            }
        }
        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 ProcessNavigation(topPage, segments, parameters, false, animated);
                await DoNavigateAction(topPage, nextSegment, topPage, parameters);
            }
            else
            {
                // Replace RootPage of NavigationStack
                var nextPage = CreatePageFromSegment(nextSegment);
                await ProcessNavigation(nextPage, segments, parameters, false, animated);
                await DoNavigateAction(topPage ?? currentPage, nextSegment, nextPage, parameters, async() =>
                {
                    var push = DoPush(currentPage, nextPage, false, animated);

                    if (clearNavigationStack && !isEmptyOfNavigationStack)
                    {
                        currentPage.Navigation.RemovePage(topPage);
                    }

                    await push;
                });
            }

            foreach (var destroyPage in destroyPages)
            {
                PageUtilities.DestroyPage(destroyPage);
            }
        }