WinRT - How to ignore or delete page from navigati

2019-04-25 02:47发布

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.

7条回答
Explosion°爆炸
2楼-- · 2019-04-25 03:11

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.

查看更多
干净又极端
3楼-- · 2019-04-25 03:11

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

查看更多
ゆ 、 Hurt°
4楼-- · 2019-04-25 03:13

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);
    }
}
查看更多
【Aperson】
5楼-- · 2019-04-25 03:15

When loading the page use

this.NavigationCacheMode = NavigationCacheMode.Disabled;
查看更多
▲ chillily
6楼-- · 2019-04-25 03:23

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);
            }
        }
    }
}
查看更多
【Aperson】
7楼-- · 2019-04-25 03:24

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;
}
查看更多
登录 后发表回答