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

如何用FlyoutPage替换Shell导航并保留原有菜单结构?

替换MAUI Shell导航为FlyoutPage实现相同菜单结构(解决页面实例复用问题)

完全可以通过替换为FlyoutPage来实现与原Shell一致的菜单结构,同时解决页面实例复用的问题。以下是对应实现方案:

核心思路

原Shell的结构分为两部分:

  • 浮出层菜单:包含一个带标签导航的Information组,以及三个独立页面(Enquiry、Search、Update)
  • 标签导航:Information组下的四个页面(Home、Favourite、Recommended、Loans)

用FlyoutPage实现时,左侧浮出层用列表展示所有菜单选项,右侧内容区域根据选中项切换:选中Information组内的页面时加载带标签页的TabbedPage,选中其他独立项时直接加载对应页面实例(每次创建新实例,避免复用)。

实现代码

1. FlyoutPage主页面(MainFlyoutPage.xaml)

<?xml version="1.0" encoding="UTF-8" ?>
<FlyoutPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
            xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
            xmlns:local="clr-namespace:LibraryAppM.Views"
            x:Class="LibraryAppM.MainFlyoutPage"
            Title="LibraryAppM">
    <!-- 左侧浮出层菜单 -->
    <FlyoutPage.Flyout>
        <ContentPage Title="Menu" BackgroundColor="White">
            <ListView x:Name="MenuListView"
                      ItemSelected="OnMenuItemSelected">
                <ListView.ItemsSource>
                    <x:Array Type="{x:Type local:MenuOption}">
                        <!-- Information组标识 -->
                        <local:MenuOption Title="Information" Icon="lib_pic.jpg" IsGroup="True"/>
                        <local:MenuOption Title="Home" Icon="home.png" TargetType="{x:Type local:MainPage}"/>
                        <local:MenuOption Title="Favourite" Icon="favourite.jpeg" TargetType="{x:Type local:FavouritePage}"/>
                        <local:MenuOption Title="Recommended" Icon="lib_pic.jpg" TargetType="{x:Type local:RecommendedPage}"/>
                        <local:MenuOption Title="Loans" Icon="lib_pic.jpg" TargetType="{x:Type local:LoansPage}"/>
                        <!-- 独立页面 -->
                        <local:MenuOption Title="Enquiry" Icon="enquiry.png" TargetType="{x:Type local:EnquiryPage}"/>
                        <local:MenuOption Title="Search" Icon="search.png" TargetType="{x:Type local:SearchPage}"/>
                        <local:MenuOption Title="Update" Icon="update.png" TargetType="{x:Type local:UpdatePage}"/>
                    </x:Array>
                </ListView.ItemsSource>
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <StackLayout Orientation="Horizontal" Padding="15,10">
                                <Image Source="{Binding Icon}" WidthRequest="25" HeightRequest="25"/>
                                <Label Text="{Binding Title}" Margin="10,0" VerticalOptions="Center"/>
                            </StackLayout>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </ContentPage>
    </FlyoutPage.Flyout>

    <!-- 默认显示的内容页 -->
    <FlyoutPage.Detail>
        <NavigationPage>
            <x:Arguments>
                <local:MainPage/>
            </x:Arguments>
        </NavigationPage>
    </FlyoutPage.Detail>
</FlyoutPage>

2. 菜单选项模型(MenuOption.cs)

namespace LibraryAppM.Views
{
    public class MenuOption
    {
        public string Title { get; set; }
        public string Icon { get; set; }
        public Type TargetType { get; set; }
        public bool IsGroup { get; set; } = false;
    }
}

3. FlyoutPage后台代码(MainFlyoutPage.xaml.cs)

namespace LibraryAppM
{
    public partial class MainFlyoutPage : FlyoutPage
    {
        public MainFlyoutPage()
        {
            InitializeComponent();
        }

        private void OnMenuItemSelected(object sender, SelectedItemChangedEventArgs e)
        {
            var option = e.SelectedItem as MenuOption;
            if (option == null || option.IsGroup)
                return;

            // 每次创建新页面实例,彻底避免复用
            Page targetPage = (Page)Activator.CreateInstance(option.TargetType);
            
            // 判断是否为Information组内页面,切换对应内容
            var infoPageTypes = new[] { typeof(MainPage), typeof(FavouritePage), typeof(RecommendedPage), typeof(LoansPage) };
            if (infoPageTypes.Contains(option.TargetType))
            {
                var tabbedPage = new TabbedPage
                {
                    Children = 
                    {
                        new MainPage { Title = "Home", IconImageSource = "home.png" },
                        new FavouritePage { Title = "Favourite", IconImageSource = "favourite.jpeg" },
                        new RecommendedPage { Title = "Recommended", IconImageSource = "lib_pic.jpg" },
                        new LoansPage { Title = "Loans", IconImageSource = "lib_pic.jpg" }
                    }
                };
                // 切换到选中的标签页
                tabbedPage.CurrentPage = tabbedPage.Children.First(c => c.GetType() == option.TargetType);
                Detail = new NavigationPage(tabbedPage);
            }
            else
            {
                Detail = new NavigationPage(targetPage);
            }

            IsPresented = false;
        }
    }
}

4. 更新App启动入口(App.xaml.cs)

namespace LibraryAppM
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
            // 替换原Shell为FlyoutPage
            MainPage = new MainFlyoutPage();
        }
    }
}

关键说明

  • 通过Activator.CreateInstance每次创建新页面实例,彻底解决Shell默认复用页面的问题
  • 左侧菜单完整还原了原Shell的选项结构,包括Information组的层级展示
  • 标签导航通过TabbedPage实现,与原Shell的Tab交互行为一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 01:34:56