WinRT - How to ignore or delete page from navigati

2019-04-25 03:04发布

问题:

I have following situation in my WinRT metro (c# - xaml) application :

User launch the application and he or she is not logged in. In the menu bar I have button which navigates them to Shopping cart. It's important to mention that they can click on it regardless of logged in/out status.

So I have this :

Home Page - > Login Page - > Shopping Cart

And everything works great, but when I try press BACK button on my Shopping Cart page I'm navigated back to Login Page, which make sense, because page is in my navigation history. But I don't want that, I want to return user to Home Page and skip login page.

My question is how to do that, and how to manipulate Frame Navigation Stack on WinRT. I tried with going Back twice, but with no luck.

Btw, my page is "LayoutAwarePage" page and I'm using NavigationService similar to this http://dotnetbyexample.blogspot.com/2012/06/navigationservice-for-winrt.html.

回答1:

You can approach it in different ways. You can make it so the back button navigates back multiple times until it reaches the home page or skips through the log in page. You could also make the log in page something that shows up outside of the navigation Frame - either on a popup or in a different layer in the application.

*Update

In 8.1 the platform introduced the BackStack and ForwardStack properties on the Frame which you can manipulate.



回答2:

I know it's old, but since Google found this page for me, maybe someone else will find this page too.

The answer, while a valid work-around, does not answer the question.

You can use this on the login page, removing it from the back stack.

if(login_was_successful == true)
{
    this.Frame.Navigate(typeof(ShoppingCard));

    if(this.Frame.CanGoBack)
    {
        this.Frame.BackStack.RemoveAt(0);
    }
}


回答3:

There is a LayoutAwarePage.cs file in the Common folder of your project. You can change the back button behaviour from this file.

 protected virtual void GoBack(object sender, RoutedEventArgs e)
        {

            while (this.Frame.CanGoBack) this.Frame.GoBack();

            // Use the navigation frame to return to the previous page
            //if (this.Frame != null && this.Frame.CanGoBack) this.Frame.GoBack();
        } 


回答4:

You can call GoHome() on the Back button event, that'll take you to HomePage or first page of the application.



回答5:

I wrote my own history tracking navigation service. You can find it here.

In case I move file or remove it, here's current version:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Navigation;
using MetroLog;
using SparkiyClient.UILogic.Services;

namespace SparkiyClient.Services
{
    public class NavigationService : INavigationService
    {
        private static readonly ILogger Log = LogManagerFactory.DefaultLogManager.GetLogger<NavigationService>();
        private readonly Dictionary<string, Type> pagesByKey = new Dictionary<string, Type>();
        private readonly Stack<PageStackEntry> historyStack = new Stack<PageStackEntry>();
        private PageStackEntry currentPage;

        public string CurrentPageKey { get; private set; }

        public bool CanGoBack => this.historyStack.Any();

        private static Frame GetFrame()
        {
            return (Frame)Window.Current.Content;
        }

        public void GoBack()
        {
            if (!this.CanGoBack)
                return;

            var item = this.historyStack.Pop();
            this.NavigateTo(item.SourcePageType.Name, item.Parameter, false);
        }

        public void GoHome()
        {
            if (!this.CanGoBack)
                return;

            var item = this.historyStack.Last();
            this.NavigateTo(item.SourcePageType.Name, item.Parameter, false);
            this.historyStack.Clear();
        }

        public void NavigateTo(string pageKey, bool addSelfToStack = true)
        {
            this.NavigateTo(pageKey, null, addSelfToStack);
        }

        public void NavigateTo<T>(bool addToStack = true)
        {
            this.NavigateTo<T>(null, addToStack);
        }

        public void NavigateTo<T>(object parameter, bool addSelfToStack = true)
        {
            this.NavigateTo(typeof(T).Name, parameter, addSelfToStack);
        }

        public void NavigateTo(string pageKey, object parameter, bool addToStack = true)
        {
            var lockTaken = false;
            Dictionary<string, Type> dictionary = null;
            try
            {
                Monitor.Enter(dictionary = this.pagesByKey, ref lockTaken);
                if (!this.pagesByKey.ContainsKey(pageKey))
                    throw new ArgumentException(string.Format("No such page: {0}. Did you forget to call NavigationService.Configure?", pageKey), "pageKey");

                if (addToStack && this.currentPage != null)
                    this.historyStack.Push(this.currentPage);

                GetFrame().Navigate(this.pagesByKey[pageKey], parameter);

                this.CurrentPageKey = pageKey;
                this.currentPage = new PageStackEntry(this.pagesByKey[pageKey], parameter, null);

                Log.Debug(this.historyStack.Reverse().Aggregate("null", (s, entry) => s + " > " + entry.SourcePageType.Name));
            }
            finally
            {
                if (lockTaken && dictionary != null)
                    Monitor.Exit(dictionary);
            }
        }

        public void Configure(string key, Type pageType)
        {
            var lockTaken = false;
            Dictionary<string, Type> dictionary = null;
            try
            {
                Monitor.Enter(dictionary = this.pagesByKey, ref lockTaken);
                if (this.pagesByKey.ContainsKey(key))
                    this.pagesByKey[key] = pageType;
                else this.pagesByKey.Add(key, pageType);
            }
            finally
            {
                if (lockTaken && dictionary != null)
                    Monitor.Exit(dictionary);
            }
        }
    }
}


回答6:

When loading the page use

this.NavigationCacheMode = NavigationCacheMode.Disabled;


回答7:

To pop from stack:

NavigationService.RemoveBackEntry();

To Navigate to the Main Menu touching the back button:

protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
    NavigationService. Navigate (new Uri ("/Main Page. xaml", UriKind.Relative));
}

To keep the user in the Main Menu even if they touch the back button:

protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
    // cancel the navigation
    e.Cancel = true;
}