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

MAUI Shell导航问题:如何从模态页跳转到非模态页?

解决.NET MAUI Shell导航模态页后跳转非模态页的问题

问题核心

用Shell模态导航打开协议页后,直接跳转Page2会导致Page2也进入模态栈;混合普通导航与Shell导航会引发导航栈混乱,出现跳转后自动返回Page1的问题。

最优方案:统一使用Shell模态导航+返回参数传递

1. 确保路由注册完成(AppShell.xaml.cs)

public partial class AppShell : Shell
{
    public AppShell()
    {
        InitializeComponent();
        Routing.RegisterRoute(nameof(AgreementPage), typeof(AgreementPage));
        Routing.RegisterRoute(nameof(Page2), typeof(Page2));
    }
}

2. Page1中的导航逻辑

// needConfirmation为判断是否需确认的布尔值,parameter为待传递参数
if (!needConfirmation)
{
    // 无需确认,直接跳转非模态Page2
    await Shell.Current.GoToAsync(nameof(Page2), new Dictionary<string, object> 
    { 
        { "TargetParameter", parameter } 
    });
}
else
{
    // 打开模态协议页,等待返回确认结果
    var navigationResult = await Shell.Current.GoToAsync(nameof(AgreementPage), new Dictionary<string, object> 
    { 
        { "TargetParameter", parameter } 
    });

    // 解析返回的确认状态
    if (navigationResult.TryGetValue("IsConfirmed", out object isConfirmedObj) && (bool)isConfirmedObj)
    {
        // 确认完成后跳转非模态Page2
        await Shell.Current.GoToAsync(nameof(Page2), new Dictionary<string, object> 
        { 
            { "TargetParameter", parameter } 
        });
    }
}

3. AgreementPage中的确认逻辑

在协议页的确认按钮点击事件中,关闭模态页并传递确认结果:

private async void ConfirmButton_Clicked(object sender, EventArgs e)
{
    // 返回确认状态至上级页面
    await Shell.Current.GoToAsync("..", new Dictionary<string, object> 
    { 
        { "IsConfirmed", true } 
    });
}

4. 协议页的模态属性设置(XAML)

确保AgreementPage配置为模态展示:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="YourNamespace.AgreementPage"
             Shell.PresentationMode="Modal">
    <!-- 页面内容 -->
</ContentPage>

方案优势

  • 全程遵循Shell导航规范,避免混合导航导致的栈混乱
  • 模态页通过GoToAsync("..")关闭并传递结果,确保模态栈完全清理后再执行Page2跳转
  • 无需依赖延迟等临时方案,逻辑稳定可靠

替代方案:MessagingCenter跨页通知跳转(适合低耦合场景)

1. Page1中订阅消息

public Page1()
{
    InitializeComponent();
    MessagingCenter.Subscribe<AgreementPage, (bool IsConfirmed, object Parameter)>(this, "NavigateToPage2", async (sender, args) =>
    {
        if (args.IsConfirmed)
        {
            await Shell.Current.GoToAsync(nameof(Page2), new Dictionary<string, object> 
            { 
                { "TargetParameter", args.Parameter } 
            });
        }
    });
}

// 页面消失时取消订阅,避免内存泄漏
protected override void OnDisappearing()
{
    base.OnDisappearing();
    MessagingCenter.Unsubscribe<AgreementPage, (bool, object)>(this, "NavigateToPage2");
}

2. AgreementPage中发送消息并关闭模态

private async void ConfirmButton_Clicked(object sender, EventArgs e)
{
    // 传递确认状态与参数
    MessagingCenter.Send(this, "NavigateToPage2", (IsConfirmed: true, Parameter: YourParameter));
    // 关闭模态页
    await Shell.Current.GoToAsync("..");
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 11:42:11