【问题标题】:How to remove particular page from modal stack?如何从模式堆栈中删除特定页面?
【发布时间】:2019-08-29 10:08:45
【问题描述】:

我有四页页面 1-page 2-page 3-page 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


【解决方案1】:

您可以使用以下辅助函数

/// <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);
}

等等……

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

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

【讨论】:

  • 谢谢让我试试这个
  • 这对我有用。您仍然可以看到带有动画和所有内容的模态弹出...但我认为这是这里许多线程中唯一值得回应的。
【解决方案2】:

RemovePage 仅支持从NavigationStack 中删除指定页面。

像这样:Navigation.RemovePage(Navigation.NavigationStack[Navigation.NavigationStack.Count - 1]);

您可以参考这个以获得更多详细信息: https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.inavigation?view=xamarin-forms

【讨论】:

    【解决方案3】:

    如果您想返回 2 页,这将起作用

            Navigation.RemovePage(Navigation.NavigationStack[Navigation.NavigationStack.Count - 2]);
            Navigation.RemovePage(this);
    

    首先我们删除当前页面之前的页面,然后是当前页面。

    【讨论】:

    • 如何从堆栈中移除当前页面??
    • @Tester Navigation.RemovePage(this);
    【解决方案4】:

    请使用await Navigation.PopModalAsync() 并通读this link 以获取有关ModalPages 的信息。

    编辑:

    尚未对其进行测试,但可以帮助理解该方法:

    
    for (var i = Navigation.NavigationStack.Count - 1; i > 0; i--)
    {
        if (Navigation.NavigationStack[i] is Page2)
        {
            return;
        }
        await Navigation.PopModalAsync();
    }
    

    【讨论】:

    • 从第 4 页导航到第 2 页后,它不应该在视图中显示两个页面(第 4 页和第 3 页)。 Navigation.PopModalAsync() 这从堆栈中删除一个页面。如何通过单击删除多个页面。我需要删除第 4 页和第 3 页。
    • 我在第 4 页按钮单击时调用了两次 PopModalPage() 方法。问题解决了。但这是优化的方式吗?
    • @Tester 这一点都不好。这不灵活,如果您必须在第 3 页和第 4 页之间添加一个页面怎么办?最好使用PopToRootAsync 并从根页面转到特定页面,或者更改您的方法。
    • Pop to Root Async 导航到第 1 页,但我需要转到第 2 页。在使用 popto root async 时,我遇到了这个异常。:System.InvalidOperationException:Android 上不支持 PopToRootAsync,请使用导航页。
    • @Tester 作为替代方法,您可以从NavigationStack 中获取最后一个Page,并将其类型与Page2 进行比较,然后弹出Pages,直到获得所需的Page。
    猜你喜欢
    • 1970-01-01
    • 2013-10-11
    • 2021-05-27
    • 1970-01-01
    • 2016-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-21
    相关资源
    最近更新 更多