You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI Shell:如何将标签页添加到导航栈?路由问题求助

解决.NET MAUI Shell中导航到标签页并保留返回栈的问题

问题根源

你遇到的错误是因为FlyoutItem是Shell的顶级导航容器,属于根级节点,不能作为导航栈的子页面使用:

  • 相对路由GoToAsync("EditPageRoute")无法导航到FlyoutItem,Shell不支持相对路由指向顶级元素
  • 绝对路由GoToAsync("//EditPageRoute")会替换整个根导航栈,导致原列表页被移除,无法返回

解决方案1:用Shell原生TabBar替代FlyoutItem

将带标签的页面结构改为ShellContent包裹的TabBar,这样可以作为导航栈的子页面被正常推送:

修改AppShell.xaml:

<FlyoutItem Title="List">
    <ShellContent ContentTemplate="{DataTemplate page:ListPage}" Route="ListPage"/>
</FlyoutItem>

<!-- 用ShellContent包裹TabBar,设置路由并隐藏在Flyout菜单 -->
<ShellContent Route="EditTabs" FlyoutItemIsVisible="False">
    <TabBar>
        <Tab Title="General Info">
            <ShellContent ContentTemplate="{DataTemplate page:EditPage}"/>
        </Tab>
        <Tab Title="Remarks">
            <ShellContent ContentTemplate="{DataTemplate page:RemarkEditPage}"/>
        </Tab>
    </TabBar>
</ShellContent>

修改ListPage.xaml.cs的导航代码(使用相对路由):

private async void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{
    var rec = e.CurrentSelection.FirstOrDefault() as TableRow;
    if (rec == null) return;
    
    var parameters = new Dictionary<string, object>
    {
        { "Id", rec.Id }
    };
    // 相对导航,自动将标签页添加到导航栈
    await Shell.Current.GoToAsync("EditTabs", parameters);
}

在子页面中接收参数(以EditPage为例):

protected override void OnNavigatedTo(NavigatedToEventArgs args)
{
    base.OnNavigatedTo(args);
    if (Shell.Current.CurrentState.NavigationParameters.TryGetValue("Id", out var idObj) 
        && idObj is int recordId)
    {
        // 根据ID加载数据
        LoadRecord(recordId);
    }
}

解决方案2:动态创建TabbedPage并推送

如果需要更灵活的标签页创建方式(比如动态增减标签),可以直接创建TabbedPage并推送到导航栈:

修改ListPage.xaml.cs:

private async void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{
    var rec = e.CurrentSelection.FirstOrDefault() as TableRow;
    if (rec == null) return;
    
    // 创建TabbedPage容器
    var tabbedPage = new TabbedPage();
    
    // 添加第一个标签页并传递数据
    var editPage = new EditPage();
    editPage.Title = "General Info";
    // 可以通过BindingContext传递数据,或者用NavigationParameter
    editPage.BindingContext = rec;
    tabbedPage.Children.Add(editPage);
    
    // 添加第二个标签页
    var remarkPage = new RemarkEditPage();
    remarkPage.Title = "Remarks";
    remarkPage.BindingContext = rec;
    tabbedPage.Children.Add(remarkPage);
    
    // 推送到导航栈,自动保留返回按钮
    await Shell.Current.Navigation.PushAsync(tabbedPage);
}

两种方案对比

  • 方案1:符合Shell的设计规范,支持Shell的导航特性(如路由参数、导航栏样式统一),适合固定标签结构的场景
  • 方案2:无需预先在Shell中定义路由,动态性更强,适合需要根据业务逻辑调整标签数量或内容的场景

内容的提问来源于stack exchange,提问作者user2114189

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 02:10:16