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

.NET MAUI检测文本框变更时取消页面Disappearing事件的问题

解决Xamarin.Forms页面退出拦截问题

你重写OnDisappearing没用的核心原因是:这个方法只是页面开始消失时的通知回调,无法中断页面的退出流程——此时页面关闭的操作已经启动,return语句根本拦不住。

要实现“有修改时弹出确认框、阻止页面退出”的需求,得从导航拦截和返回事件拦截入手,分两种场景处理:


1. 处理安卓物理返回键

重写页面的OnBackButtonPressed方法,这个方法返回true就能阻止默认的返回行为:

protected override bool OnBackButtonPressed()
{
    bool hasChanges = FindChanges();
    if (hasChanges)
    {
        // 异步弹出确认框,避免阻塞UI线程
        Device.BeginInvokeOnMainThread(async () =>
        {
            bool confirmExit = await DisplayAlert("提示", "不保存就退出?", "确定", "取消");
            if (confirmExit)
            {
                // 用户确认后,手动执行页面退出
                await Navigation.PopAsync();
            }
        });
        // 返回true,阻止系统默认的返回逻辑
        return true;
    }
    // 无修改时,执行默认返回
    return base.OnBackButtonPressed();
}

2. 处理导航栏返回按钮(iOS/安卓通用)

默认的导航栏返回按钮不会触发OnBackButtonPressed,需要通过NavigationPage的Navigating事件全局拦截,或者在页面内替换自定义返回按钮:

方案A:全局导航拦截(推荐)

在App.xaml.cs里监听导航事件,统一处理所有页面的退出拦截:

public App()
{
    InitializeComponent();
    var rootNav = new NavigationPage(new HomePage());
    rootNav.Navigating += HandleNavigating;
    MainPage = rootNav;
}

private async void HandleNavigating(object sender, NavigatingEventArgs e)
{
    // 判断是否是返回上一页的操作
    if (e.NavigationMode == NavigationMode.Pop)
    {
        var currentPage = e.Navigation.NavigationStack.LastOrDefault();
        // 替换成你的页面类型
        if (currentPage is EditableContentPage editablePage)
        {
            bool hasChanges = editablePage.FindChanges();
            if (hasChanges)
            {
                // 取消当前导航操作
                e.Cancel = true;
                // 弹出确认框
                bool confirmExit = await editablePage.DisplayAlert("提示", "不保存就退出?", "确定", "取消");
                if (confirmExit)
                {
                    // 用户确认后,重新执行退出
                    await e.Navigation.PopAsync();
                }
            }
        }
    }
}

注意:需要把FindChanges方法改为public,让全局事件能访问到页面的修改状态。

方案B:页面内自定义返回按钮

如果只需要单个页面处理,可以替换默认导航栏返回按钮:

protected override void OnAppearing()
{
    base.OnAppearing();
    if (Navigation != null && NavigationPage.GetHasNavigationBar(this))
    {
        // 隐藏默认返回按钮的文字(可选)
        NavigationPage.SetBackButtonTitle(this, "");
        // 添加自定义返回按钮
        var customBack = new ToolbarItem
        {
            Text = "返回",
            IconImageSource = "back_icon.png", // 可选,设置返回图标
            Order = ToolbarItemOrder.Primary
        };
        customBack.Clicked += async (s, e) =>
        {
            bool hasChanges = FindChanges();
            if (hasChanges)
            {
                bool confirmExit = await DisplayAlert("提示", "不保存就退出?", "确定", "取消");
                if (confirmExit)
                {
                    await Navigation.PopAsync();
                }
            }
            else
            {
                await Navigation.PopAsync();
            }
        };
        ToolbarItems.Add(customBack);
    }
}

关键注意点

  • 不要依赖OnDisappearing做拦截,它的设计目的是让页面做清理工作,而非阻止页面关闭。
  • 所有弹窗操作必须异步执行,避免阻塞UI线程,用DisplayAlert的返回值判断用户选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 17:45:25