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

.NET MAUI Shell带查询属性导航页面加载异常排查

MAUI Shell导航异常问题解决

问题现象

  • 应用启动后默认显示UniquePage;
  • 首次点击Flyout的「Variant 1」「Variant 2」可正常加载VariantPage并显示对应参数标题;
  • 切换回UniquePage后,再次点击任何Variant项,页面停留在UniquePage,后续所有导航操作失效。

核心原因

  1. 单例服务冲突:VariantPage和VariantViewModel被注册为Singleton,导致两个FlyoutItem共用同一个页面实例,Shell导航逻辑混乱,无法区分不同参数的Variant导航请求;
  2. 查询参数加载时机错误:ViewModel构造函数中直接调用LoadWidgets(),此时Side属性尚未通过QueryProperty完成赋值,且参数更新时未触发重新加载;
  3. 路由配置不规范:两个Variant项的路由均指向VariantPage?Side=XXX,Shell无法识别为独立的导航目标,导致导航状态冲突。

解决方案

1. 调整服务注册生命周期

将VariantPage和VariantViewModel改为Transient,确保每次导航都生成新实例(或按需复用但能正确更新参数):

// MauiProgram.cs
builder.Services.AddSingleton<ConfigurationService>();
// 改为Transient,每次导航创建新实例
builder.Services.AddTransient<VariantViewModel>();
builder.Services.AddTransient<VariantPage>();
// Unique相关保持Singleton不影响
builder.Services.AddSingleton<UniqueViewModel>();
builder.Services.AddSingleton<UniquePage>();

2. 修正查询参数与数据加载逻辑

利用CommunityToolkit.Mvvm的属性变更回调,在Side参数更新时重新加载数据,确保参数生效:

// VariantViewModel.cs
[ObservableProperty]
private string side = "Left";

// 添加属性变更回调,参数更新时重新加载数据
partial void OnSideChanged(string value)
{
    LoadWidgets();
}

public VariantViewModel(ConfigurationService service)
{
    this.configService = service;
    // 移除构造函数中的LoadWidgets(),避免参数未赋值时加载
    // LoadWidgets();
}

3. 规范Shell路由配置

修改AppShell的路由定义,移除硬编码参数,通过绝对路由确保导航目标唯一:

<!-- AppShell.xaml -->
<FlyoutItem Title="Unique">
    <Tab>
        <ShellContent
            ContentTemplate="{DataTemplate local:MVVM.View.UniquePage}"
            Route="UniquePage" />
    </Tab>
</FlyoutItem>
<FlyoutItem Title="Variant 1" Clicked="Variant1Clicked">
    <Tab>
        <ShellContent
            ContentTemplate="{DataTemplate local:MVVM.View.VariantPage}"
            Route="VariantPage" />
    </Tab>
</FlyoutItem>
<FlyoutItem Title="Variant 2" Clicked="Variant2Clicked">
    <Tab>
        <ShellContent
            ContentTemplate="{DataTemplate local:MVVM.View.VariantPage}"
            Route="VariantPage" />
    </Tab>
</FlyoutItem>

在AppShell代码后台添加导航逻辑,使用绝对路由传递参数:

// AppShell.xaml.cs
public AppShell()
{
    InitializeComponent();
    // 注册路由模板
    Routing.RegisterRoute(nameof(VariantPage), typeof(VariantPage));
    Routing.RegisterRoute(nameof(UniquePage), typeof(UniquePage));
}

private async void Variant1Clicked(object sender, EventArgs e)
{
    await Shell.Current.GoToAsync($"//{nameof(VariantPage)}?Side=Test1");
}

private async void Variant2Clicked(object sender, EventArgs e)
{
    await Shell.Current.GoToAsync($"//{nameof(VariantPage)}?Side=Test2");
}

4. 优化页面导航生命周期

在VariantPage中确保导航时正确接收参数,可手动验证参数传递:

// VariantPage.cs
protected override void OnNavigatedTo(NavigatedToEventArgs args)
{
    base.OnNavigatedTo(args);
    // 可选:手动获取查询参数,确认参数传递正常
    if (Shell.Current.CurrentState.Location.QueryParsed.TryGetValue("Side", out var side))
    {
        ((VariantViewModel)BindingContext).Side = side;
    }
}

验证效果

完成以上修改后,测试导航流程:

  1. 启动应用→显示UniquePage;
  2. 点击Variant1/Variant2→加载对应参数的VariantPage;
  3. 切回UniquePage→正常显示;
  4. 再次点击Variant1/Variant2→可正常切换到对应页面,参数生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 02:52:56