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

.NET Maui Blazor应用:退出发起确认弹窗及关闭前方法咨询

解决方案:Blazor .NET MAUI混合应用返回关闭确认弹窗

问题根源

你之前使用Window.Deactivated事件是错误的——这个事件会在应用失去焦点时触发(比如切换到其他App、锁屏、按Home键),并非仅在用户主动关闭应用时触发,所以重启应用时的状态变化会误触弹窗。

正确实现方式

需要分两种场景处理:移动端物理返回按钮、Blazor页面内的导航返回,同时在真正关闭应用时做清理工作。

1. 处理移动端物理返回按钮

重写Application类的OnBackButtonPressedAsync方法,这是MAUI专门用于拦截物理返回按钮的方法,仅在用户按下返回键时触发:

public partial class App : Application
{
    private IAudioPlayer _audioPlayer;
    private IAudioManager _audioManager;

    public App(IAudioManager audioManager)
    {
        InitializeComponent();
        MainPage = new MainPage();
        _audioManager = audioManager;
        // 初始化_audioPlayer(根据你的业务逻辑补充)
        _audioPlayer = _audioManager.CreatePlayer();
    }

    // 拦截物理返回按钮
    protected override async Task<bool> OnBackButtonPressedAsync()
    {
        // 判断是否处于Blazor根页面(根据你的路由结构调整判断逻辑)
        var blazorWebView = MainPage as BlazorWebView;
        if (blazorWebView != null)
        {
            var navManager = blazorWebView.Services.GetRequiredService<NavigationManager>();
            // 假设根路由为"/",判断当前是否在根页面
            if (navManager.Uri.EndsWith("/"))
            {
                bool confirmClose = await MainPage.DisplayAlert("确认", "是否要关闭应用?", "是", "否");
                if (confirmClose)
                {
                    // 关闭前清理资源
                    _audioPlayer?.Stop();
                    // 允许系统关闭应用
                    return await base.OnBackButtonPressedAsync();
                }
                else
                {
                    // 阻止默认返回行为
                    return true;
                }
            }
        }
        // 非根页面,允许正常返回上一页
        return await base.OnBackButtonPressedAsync();
    }

    // 应用进入后台时的资源清理(可选)
    protected override void OnSleep()
    {
        _audioPlayer?.Stop();
        base.OnSleep();
    }

    // 应用真正退出时的最终清理
    protected override void OnQuit()
    {
        _audioPlayer?.Dispose();
        base.OnQuit();
    }
}

2. 处理Blazor页面内的导航返回

如果用户在Blazor页面中点击浏览器返回按钮(或调用导航返回),需要通过NavigationManager拦截导航事件,判断是否为根页面返回:

在Blazor的布局组件(比如MainLayout.razor)中添加以下代码:

@inject NavigationManager NavManager
@inject IJSRuntime JSRuntime

@code {
    protected override void OnInitialized()
    {
        // .NET 7+推荐使用BeforeLocationChanged拦截导航
        NavManager.BeforeLocationChanged += HandleBeforeLocationChanged;
        base.OnInitialized();
    }

    private async Task HandleBeforeLocationChanged(object? sender, BeforeLocationChangedEventArgs e)
    {
        // 判断当前是否在根页面,且是返回操作
        if (NavManager.Uri.EndsWith("/"))
        {
            bool confirmClose = await JSRuntime.InvokeAsync<bool>("confirm", "是否要关闭应用?");
            if (!confirmClose)
            {
                // 取消导航
                e.Cancel = true;
            }
            else
            {
                // 调用MAUI的退出方法
                await App.Current.MainPage.InvokeAsync(() =>
                {
                    App.Current.Quit();
                });
            }
        }
    }

    public void Dispose()
    {
        NavManager.BeforeLocationChanged -= HandleBeforeLocationChanged;
    }
}

关键说明

  • 不要用Window.Deactivated:该事件触发场景太宽泛,不适合做关闭确认。
  • 应用关闭前的清理:使用OnQuit或Window.Destroying事件做资源释放(比如停止音频),这些事件仅在应用真正退出时触发。
  • 路由判断:根据你的实际路由结构调整根页面的判断逻辑,确保只有在用户从根页面返回时才弹出确认弹窗。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 16:23:23