MAUI如何从代码后台/ViewModel导航FlyoutItem并同步选中状态
MAUI Shell代码导航复用页面实例的解决办法
问题出在哪
直接用Shell.Current.GoToAsync(nameof(PageTwo))会默认在当前导航栈上新建页面实例,而侧边栏里的页面属于Shell的根级导航项,点击侧边栏是切换已存在的根页面实例,不会新增导航栈,所以才会出现返回箭头、丢失页面状态的情况。
几种解决方法
1. 使用绝对路径导航
页面默认会以自身名称作为Shell路由,导航时给路径加上//前缀(绝对路径),就能直接切换到根级的已存在页面实例,不会新建:
// 在ViewModel或代码后台中执行导航 await Shell.Current.GoToAsync($"//{nameof(PageTwo)}");
2. 指定FlyoutItem的路由名称导航
如果你的FlyoutItem在AppShell.xaml里显式设置了Route属性,直接导航到该路由更稳妥:
假设AppShell.xaml配置如下:
<FlyoutItem Title="首页" Route="HomeTab"> <ShellContent ContentTemplate="{DataTemplate local:PageOne}" /> </FlyoutItem> <FlyoutItem Title="页面二" Route="PageTwoTab"> <ShellContent ContentTemplate="{DataTemplate local:PageTwo}" /> </FlyoutItem> <FlyoutItem Title="页面三" Route="PageThreeTab"> <ShellContent ContentTemplate="{DataTemplate local:PageThree}" /> </FlyoutItem>
导航时直接调用FlyoutItem的路由:
await Shell.Current.GoToAsync("//PageTwoTab");
3. 切换Shell的CurrentItem(适配MVVM场景)
用CommunityToolkit.MVVM时,在ViewModel里直接修改Shell的CurrentItem,和点击侧边栏的行为完全一致:
先在ViewModel中定义导航命令:
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Microsoft.Maui.Controls; using System.Linq; public class MainViewModel : ObservableObject { public ICommand GoToPageTwoCmd { get; } public MainViewModel() { GoToPageTwoCmd = new RelayCommand(NavigateToPageTwo); } private void NavigateToPageTwo() { if (Shell.Current is AppShell appShell) { // 找到对应路由的FlyoutItem var pageTwoItem = appShell.Items.FirstOrDefault(i => i.Route == "PageTwoTab") as FlyoutItem; if (pageTwoItem != null) { appShell.CurrentItem = pageTwoItem; } } } }
然后在页面中绑定该命令(比如底部按钮):
<Button Text="跳转到页面二" Command="{Binding GoToPageTwoCmd}" />
额外提示
无论用哪种方式,都要避免使用无前缀的相对路径导航,坚持用绝对路径或CurrentItem切换的方式,这样既能复用页面实例、保留状态,也能自动同步侧边栏的选中状态,和手动点击侧边栏的效果完全一致。
内容的提问来源于stack exchange,提问作者Ray
相关产品推荐
相关产品推荐

