Пример #1
0
        protected static async Task DoNavigateAction(Page fromPage, string toSegment, Page toPage, INavigationParameters parameters, Func <Task> navigationAction = null, Action onNavigationActionCompleted = null)
        {
            var segmentParameters = UriParsingHelper.GetSegmentParameters(toSegment, parameters);

            segmentParameters.GetNavigationParametersInternal().Add(KnownInternalParameters.NavigationMode, NavigationMode.New);

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

            if (!canNavigate)
            {
                return;
            }

            OnNavigatingTo(toPage, segmentParameters);

            if (navigationAction != null)
            {
                await navigationAction();
            }

            OnNavigatedFrom(fromPage, segmentParameters);

            onNavigationActionCompleted?.Invoke();

            OnNavigatedTo(toPage, segmentParameters);
        }
        /// <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);
        }
Пример #4
0
        public static async Task <INavigationResult> GoBackToRootInvokeCurrentPageOnNavigatedToInternal(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

                Page page        = PageUtilities.GetCurrentPage(Application.Current.MainPage);
                var  canNavigate = await PageUtilities.CanNavigateAsync(page, parameters);

                if (!canNavigate)
                {
                    result.Exception = new NavigationException(NavigationException.IConfirmNavigationReturnedFalse, page);
                    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

                await page.Navigation.PopToRootAsync();

                foreach (var destroyPage in pagesToDestroy)
                {
                    PageUtilities.OnNavigatedFrom(destroyPage, parameters);
                    PageUtilities.DestroyPage(destroyPage);
                }

                Page currentPage = PageUtilities.GetCurrentPage(root);

                PageUtilities.OnNavigatedTo(currentPage, parameters);

                result.Success = true;
                return(result);
            }
            catch (Exception ex)
            {
                result.Exception = ex;
                return(result);
            }
        }
        private static async Task <INavigationResult> SelectTabAsync(INavigationService navigationService, INavigationParameters parameters, Func <TabbedPage, Page> targetPageProvider)
        {
            try {
                var currentPage = ((IPageAware)navigationService).Page;

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

                if (!canNavigate)
                {
                    throw new Exception($"IConfirmNavigation for {currentPage} returned false");
                }

                TabbedPage tabbedPage = null;

                if (currentPage.Parent is TabbedPage parent)
                {
                    tabbedPage = parent;
                }
                else if (currentPage.Parent is NavigationPage navPage)
                {
                    if (navPage.Parent != null && navPage.Parent is TabbedPage parent2)
                    {
                        tabbedPage = parent2;
                    }
                }

                if (tabbedPage == null)
                {
                    throw new Exception("No parent TabbedPage could be found");
                }

                Page target = targetPageProvider.Invoke(tabbedPage);

                var tabParameters = UriParsingHelper.GetSegmentParameters(target.GetType().Name, parameters);

                tabbedPage.CurrentPage = target;
                PageUtilities.OnNavigatedFrom(currentPage, tabParameters);
                PageUtilities.OnNavigatedTo(target, tabParameters);
            } catch (Exception ex) {
                return(new NavigationResult {
                    Exception = ex
                });
            }

            return(new NavigationResult {
                Success = true
            });
        }
        /// <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>
        public static async Task GoBackToRootAsync(this INavigationService navigationService, NavigationParameters parameters = null)
        {
            try
            {
                if (parameters == null)
                {
                    parameters = new NavigationParameters();
                }

                parameters.InternalParameters.Add(KnownInternalParameters.NavigationMode, NavigationMode.Back);

                IPageAware pageAware = (IPageAware)navigationService;

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

                if (!canNavigate)
                {
                    return;
                }

                List <Page> pagesToDestroy = pageAware.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 pageAware.Page.Navigation.PopToRootAsync();

                //BOOM!
                foreach (var destroyPage in pagesToDestroy)
                {
                    PageUtilities.OnNavigatedFrom(destroyPage, parameters);
                    PageUtilities.DestroyPage(destroyPage);
                }

                PageUtilities.OnNavigatedTo(root, parameters);
            }
            catch (InvalidOperationException ex)
            {
                throw new InvalidOperationException("GoBackToRootAsync can only be called when the calling Page is within a NavigationPage.", ex);
            }
            catch
            {
                throw;
            }
        }
Пример #7
0
        private async Task <NavigationResult> PeekPreviousRegion(INavigationParameters parameters)
        {
            var result = new NavigationResult();

            try
            {
                var currentRegion = PagesContainer[NavigationHistory.Pop()];

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

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

                if (NavigationHistory.Count == 0)
                {
                    //TODO: exit the application.
                    //_applicationProvider..Quit();
                    result.Success = true;
                    return(result);
                }

                var previousRegion = PagesContainer[NavigationHistory.Peek()];
                GetContentPresenter().Content = previousRegion;

                PageUtilities.OnNavigatedFrom(currentRegion, parameters);
                PageUtilities.OnNavigatedTo(previousRegion, parameters);

                if (CurrentRegionName.Contains('/'))
                {
                    PopRegion(currentRegion);
                }
                CurrentRegionName = NavigationHistory.Peek();

                result.Success = true;
                return(result);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                result.Exception = ex;
                return(result);
            }
        }
Пример #8
0
        /// <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 async virtual Task GoBackToRootInternal(NavigationParameters parameters)
        {
            try
            {
                if (parameters == null)
                {
                    parameters = new NavigationParameters();
                }

                parameters.AddInternalParameter(KnownInternalParameters.NavigationMode, NavigationMode.Back);

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

                if (!canNavigate)
                {
                    return;
                }

                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 page.Navigation.PopToRootAsync();

                foreach (var destroyPage in pagesToDestroy)
                {
                    PageUtilities.OnNavigatedFrom(destroyPage, parameters);
                    PageUtilities.DestroyPage(destroyPage);
                }

                PageUtilities.OnNavigatedTo(root, parameters);
            }
            catch (InvalidOperationException ex)
            {
                throw new InvalidOperationException("GoBackToRootAsync can only be called when the calling Page is within a NavigationPage.", ex);
            }
            catch
            {
                throw;
            }
        }
Пример #9
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);
        }
Пример #10
0
        public static async Task <INavigationResult> SelectTabAsync(this INavigationService navigationService, string name, INavigationParameters parameters = null)
        {
            NavigationResult navigationResult = new NavigationResult {
                Success = true
            };

            try
            {
                var currentPage = ((IPageAware)navigationService).Page;
                var canNavigate = await PageUtilities.CanNavigateAsync(currentPage, parameters);

                if (!canNavigate)
                {
                    throw new Exception($"IConfirmNavigation for {currentPage} returned false");
                }
                TabbedPage tabbedPage = null;
                if (currentPage is TabbedPage)
                {
                    tabbedPage = currentPage as TabbedPage;
                }
                if (currentPage.Parent is TabbedPage parent)
                {
                    tabbedPage = parent;
                }
                else if (currentPage.Parent is NavigationPage navPage)
                {
                    if (navPage.Parent != null && navPage.Parent is TabbedPage parent2)
                    {
                        tabbedPage = parent2;
                    }
                }
                if (tabbedPage == null)
                {
                    throw new Exception("No parent TabbedPage could be found");
                }
                var tabToSelectedType = PageNavigationRegistry.GetPageType(UriParsingHelper.GetSegmentName(name));
                if (tabToSelectedType is null)
                {
                    throw new Exception($"No View Type has been registered for '{name}'");
                }
                Page target = null;
                foreach (var child in tabbedPage.Children)
                {
                    if (child.GetType() == tabToSelectedType)
                    {
                        target = child;
                        break;
                    }
                    if (child is NavigationPage childNavPage)
                    {
                        if (childNavPage.CurrentPage.GetType() == tabToSelectedType ||
                            childNavPage.RootPage.GetType() == tabToSelectedType)
                        {
                            target = child;
                            break;
                        }
                    }
                }
                if (target is null)
                {
                    throw new Exception($"Could not find a Child Tab for '{name}'");
                }
                var tabParameters = UriParsingHelper.GetSegmentParameters(name, parameters);
                tabbedPage.CurrentPage = target;
                PageUtilities.OnNavigatedFrom(currentPage, tabParameters);
                PageUtilities.OnNavigatedTo(target, tabParameters);
            }
            catch (Exception ex)
            {
                navigationResult = new NavigationResult {
                    Exception = ex
                };
            }
            return(navigationResult);
        }
Пример #11
0
        private async Task <NavigationResult> PushRegion(string path, INavigationParameters parameters)
        {
            var result = new NavigationResult();

            try
            {
                View currentRegion = null;
                parameters = GetParams(path, parameters);

                if (PagesContainer.Count > 0)
                {
                    currentRegion = PagesContainer.Last().Value;
                    var canNavigate = await PageUtilities.CanNavigateAsync(currentRegion, parameters);

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

                View nextRegion = null;
                if (path.Contains('/'))
                {
                    foreach (var splitPath in path.Split(new[] { '/' },
                                                         StringSplitOptions.RemoveEmptyEntries))
                    {
                        if (PagesContainer.Keys.Contains(splitPath))
                        {
                            continue;
                        }
                        nextRegion = _containerProvider.ResolveRegion(splitPath);
                        PagesContainer.Add(splitPath, nextRegion);
                    }
                }
                else if (PagesContainer.Keys.Contains(path))
                {
                    nextRegion = PagesContainer[path];
                }
                else
                {
                    nextRegion = _containerProvider.ResolveRegion(path);
                    PagesContainer.Add(path, nextRegion);
                }

                GetContentPresenter().Content = nextRegion;

                await PageUtilities.OnInitializedAsync(currentRegion, parameters);

                PageUtilities.OnNavigatedFrom(currentRegion, parameters);
                PageUtilities.OnNavigatedTo(nextRegion, parameters);

                CurrentRegionName = path;
                NavigationHistory.Push(CurrentRegionName);

                result.Success = true;
                return(result);
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                result.Exception = ex;
                return(result);
            }
        }
Пример #12
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);
            }
        }