微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Xamarin Forms Shell-导航到旧的导航堆栈,而不是弹出页面

如何解决Xamarin Forms Shell-导航到旧的导航堆栈,而不是弹出页面

我的Xamarin Forms Shell应用出现问题。我不确定这是错误还是预期的行为,有人可以向我指出正确的方向。

我在Visual Shell层次结构中有一个包含2个页面的应用程序:

搜索和历史记录

<FlyoutItem Title="Search" Icon="search.png">
    <Tab Title="Search">
        <ShellContent Route="searchpage">
            <views:SearchPage />
        </ShellContent>
    </Tab>
</FlyoutItem>
<FlyoutItem Title="History" Icon="history.png">
    <Tab Title="History">
        <ShellContent>
            <views:HistoryPage />
        </ShellContent>
    </Tab>
</FlyoutItem>

注册了多个页面(我们将其分别称为PageA,PageB和PageC):

Routing.RegisterRoute("PageA",typeof(PageA));    
Routing.RegisterRoute("PageB",typeof(PageB));    
Routing.RegisterRoute("PageC",typeof(PageC)); (Oops,I should probably use nameof here)

无论如何,我先从“搜索页面开始,然后导航到PageA:

Shell.Current.GoToAsync("PageA");

因为PageA不在视觉层次结构中,所以这给了我这样的导航堆栈:

"//searchpage/PageA"

使用相同的相对导航方法,我先导航到PageB,然后导航到PageC,所以我的导航堆栈如下:

"//searchpage/PageA/PageB/PageC"

在PageC中,我使用弹出菜单导航至“历史记录”,历史记录页面可以正常打开。

现在在历史记录页面上,我再次使用弹出菜单,然后单击“搜索标签

但是我并没有像预期的那样进入搜索页面,而是回到了PageC(回到了我以前的导航堆栈)。

如果我再次使用弹出菜单并单击“搜索”选项卡,则在此页面(PageC)中,它会正确导航到“搜索页面

当从弹出菜单中选择“搜索”选项卡时,该如何工作以及如何停止导航到PageC?

谢谢

(ps-我目前正在使用Xamarin Forms 4.7)

解决方法

我将在5分钟后提出此功能请求,但我已找到解决该问题的方法。

  1. 我将最后一页(PageC)设置为根页面,并将其从我的路线脚本中删除。为此,我将以下内容添加到AppShell.Xaml中:

    <ShellItem Route="PageC">
        <ShellContent ContentTemplate="{DataTemplate views:PageC}" />
    </ShellItem>
    
    and removing this code:
    Routing.RegisterRoute("PageC",typeof(PageC));
    
  2. 现在导航到PageC时,我不再使用相对导航推入堆栈,现在我导航到这样的根页面:

     await Shell.Current.GoToAsync("//PageC");
    
  3. 在导航到PageC之前,我们需要清除当前导航堆栈。我尝试了PopToRootAsync,但这在导航到PageC之前显示了SearchPage。我发现以下代码有效:

         // FYI - Navigation Stack: //SearchPage/PageA/PageB
    
         var pageB = Shell.Current.Navigation.NavigationStack[2];
         var pageA = Shell.Current.Navigation.NavigationStack[1];
    
         Shell.Current.Navigation.RemovePage(pageB);
         Shell.Current.Navigation.RemovePage(pageA);
    
         // Now navigate to our route page,PageC.
         await Shell.Current.GoToAsync("//PageC");
    

我将使用一种更为优雅的方式来获取页面,而不是对索引进行硬编码,但是我认为这是演示正在发生的事情的最简单方法。

下一次我现在导航到SearchPage时,我将获得SearchPage

,

我认为这个功能是故意的。需要理解的一件事是,如文档中所述,每个 Tab 都包含单独的导航堆栈,Shell.Current.Navigation 指向当前活动/可见的 Tab 导航堆栈。所以你能做的其实很简单。

您只需覆盖 Shell.OnNavigating 事件,并且仅当您在不同的路由树之间导航时,从当前导航堆栈中移除除根页面之外的所有页面。

比如,从 //route1/page1 到 //route2/page2。

您可以根据您的用例调整以下代码。

public partial class AppShell : Xamarin.Forms.Shell
{
    public AppShell()
    {
        InitializeComponent();

        Setup.RegisterRoutes(this);
    }

    protected override void OnNavigating(ShellNavigatingEventArgs args)
    {
        base.OnNavigating(args);

        if (args.Current != null && args.Target != null && args.Current.Location.OriginalString.StartsWith("//") && args.Target.Location.OriginalString.StartsWith("//")) {
            var currentRoot = args.Current.Location.OriginalString.TrimStart('/').Split('/').First();
            var targetRoot = args.Target.Location.OriginalString.TrimStart('/').Split('/').First();
            
            // we are navigating between tabs
            if (!string.Equals(currentRoot,targetRoot,StringComparison.OrdinalIgnoreCase) && Navigation.NavigationStack.Count > 1) {
                for (var i = Navigation.NavigationStack.Count - 1; i > 0; i--) {
                    Navigation.RemovePage(Navigation.NavigationStack[i]);
                }
            }
        }
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。