首页 > 解决方案 > 如何从模式堆栈中删除特定页面?

问题描述

我有四页第 1 页第 2 页第 3 页第 4 页。我使用推送模式异步进行向前导航。当我在第 4 页中点击按钮时,它正在导航到第 2 页。但是在第 2 页点击后退按钮会显示堆栈页面的所有历史记录。那么如何从模态堆栈中删除页面。我也使用了 navigation.Remove(page) 但它引发了异常。请指导。

foreach (var page in Navigation.ModalStack)
{
    if (page is Page3)
    {
        await PopModalPage();
    }
}

foreach (var page in Navigation.ModalStack)
{
    if (page is Page4)
    {
        await PopModalPage();
    }
}

要从第 4 页导航到第 2 页,我正在使用此代码还有比这更优化的方式吗?

标签: c#xamarin.forms

解决方案


您可以使用以下辅助函数

/// <summary>
/// Class with extension methods for INavigation interface to help working with the modal page stack
/// </summary>
public static class ModalHelper
{
    /// <summary>
    /// Unwinds the modal stack of the navigation until reaching a page with the given type
    /// </summary>
    /// <typeparam name="PageType"></typeparam>
    /// <param name="navigation">The navigation object of the current top page</param>
    /// <returns></returns>
    public async static Task UnwindModalStackTo<PageType>(this INavigation navigation) where PageType : Page
    {
        await navigation.UnwindModalStackTo(p => p is PageType);
    }

    /// <summary>
    /// Unwinds the modal stack of the navigation until reaching the given page 
    /// </summary>
    /// <param name="navigation">The navigation object of the current top page</param>
    /// <param name="page">The page where to stop unwinding the modal stack</param>
    public async static Task UnwindModalStackTo(this INavigation navigation, Page page) 
    {
        await navigation.UnwindModalStackTo(p => p == page);
    }

    /// <summary>
    /// Unwinds the modal stack of the navigation until reaching a page that fulfils the predicate
    /// </summary>
    /// <param name="navigation">The navigation object of the current top page</param>
    /// <param name="predicate">A function which tests whether to stop at a given page</param>
    public async static Task UnwindModalStackTo(this INavigation navigation, Func<Page, bool> predicate)
    {
        bool found = false;

        while (navigation != null && navigation.ModalStack.Count > 0)
        {
            // Get the current top page of the modal stack
            Page topPage = navigation.ModalStack[navigation.ModalStack.Count - 1];

            // Get the second page in the modal stack from the top (This one will become top next after we pop)
            Page parentPage;
            if (navigation.ModalStack.Count > 1)
            {
                parentPage = navigation.ModalStack[navigation.ModalStack.Count - 2];
            }
            else
            {
                parentPage = null;
            }

            // When the top page fulfills the predicate, stop
            if (predicate(topPage))
            {
                found = true;
                break;
            }

            // Pop the top page
            await navigation.PopModalAsync();

            // We need to use the navigation of the new top page from here on
            navigation = parentPage?.Navigation;
        }

        // When the target page was not found, throw an exception
        if (!found)
        {
            throw new Exception("Desired page not found in modal stack");
        }
    }

}

请注意,在我们从堆栈中弹出顶部模式页面后,我们必须使用新顶部页面中的导航才能继续。


例子:

假设我们有一个包含五个页面的应用程序:MainPage、Page1、Page2、Page3、Page4。

Mainpage 有一个打开 Page1 modal 的按钮,Page1 有一个打开 Page2 modal 的按钮,依此类推。

在主页中:

private async void Button_Clicked(object sender, EventArgs e)
{
    Page p = new Page1();
    await Navigation.PushModalAsync(p);
}

在第 1 页中:

private async void Button_Clicked(object sender, EventArgs e)
{
    Page p = new Page2();
    await Navigation.PushModalAsync(p);
}

等等...

现在在第 4 页中(为了返回第 2 页),我们使用以下代码关闭所有打开的模式页面,直到到达第 2 页。

private async void Button_Clicked(object sender, EventArgs e)
{
    await Navigation.UnwindModalStackTo<Page2>();
}

推荐阅读