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

.NET Maui:如何阻止用户离开存在未保存数据的页面?

在.NET Maui Shell中实现未保存数据的离开确认

1. 定义通用接口与页面状态标识

先创建一个统一接口,让需要处理未保存数据的页面实现它,方便后续统一拦截逻辑:

public interface IHasUnsavedChanges
{
    bool HasUnsavedChanges { get; set; }
}

然后在你的编辑页面里实现这个接口,同时添加状态变更逻辑(比如用户输入内容时标记为未保存):

public partial class EditPage : ContentPage, IHasUnsavedChanges
{
    public bool HasUnsavedChanges { get; set; } = false;

    // 示例:用户编辑文本时标记未保存状态
    private void OnContentTextChanged(object sender, TextChangedEventArgs e)
    {
        HasUnsavedChanges = true;
    }

    // 保存数据后重置状态
    private async void OnSaveClicked(object sender, EventArgs e)
    {
        // 执行你的数据保存逻辑
        // ...
        
        HasUnsavedChanges = false;
        await Shell.Current.GoToAsync("..");
    }
}

2. 全局拦截Shell导航事件

在AppShell.xaml.cs中注册Navigating事件,统一处理所有Shell触发的导航(包括侧边菜单、导航栏返回、Tab切换等场景):

public partial class AppShell : Shell
{
    public AppShell()
    {
        InitializeComponent();
        Navigating += OnShellNavigating;
    }

    private async void OnShellNavigating(object sender, ShellNavigatingEventArgs e)
    {
        // 检查当前页面是否存在未保存变更
        if (Current.CurrentPage is IHasUnsavedChanges unsavedPage && unsavedPage.HasUnsavedChanges)
        {
            // 先取消默认导航动作
            e.Cancel();

            // 弹出确认提示框
            var confirmLeave = await unsavedPage.DisplayAlert(
                "未保存的更改",
                "你有未保存的数据,离开将丢弃这些内容,确定要离开吗?",
                "离开",
                "留在页面");

            if (confirmLeave)
            {
                // 用户确认离开,重置状态后执行导航
                unsavedPage.HasUnsavedChanges = false;
                await Current.GoToAsync(e.Target, e.Animated);
            }
        }
    }
}

3. 处理Android物理返回按钮

Android的物理返回按钮不会触发Shell的Navigating事件,需要在页面中重写OnBackButtonPressed方法处理:

protected override async bool OnBackButtonPressed()
{
    if (HasUnsavedChanges)
    {
        var confirmLeave = await DisplayAlert(
            "未保存的更改",
            "你有未保存的数据,离开将丢弃这些内容,确定要离开吗?",
            "离开",
            "留在页面");

        if (confirmLeave)
        {
            HasUnsavedChanges = false;
            return await base.OnBackButtonPressed();
        }
        else
        {
            return true; // 阻止返回动作
        }
    }
    return await base.OnBackButtonPressed();
}

4. 处理页面内自定义导航控件

如果页面里有自定义的取消/返回按钮,不要直接调用导航,先检查未保存状态:

private async void OnCancelClicked(object sender, EventArgs e)
{
    if (HasUnsavedChanges)
    {
        var confirmLeave = await DisplayAlert(
            "未保存的更改",
            "你有未保存的数据,离开将丢弃这些内容,确定要离开吗?",
            "离开",
            "留在页面");

        if (!confirmLeave) return;

        HasUnsavedChanges = false;
    }

    await Shell.Current.GoToAsync("..");
}

关键注意点

  • 保存数据后务必及时将HasUnsavedChanges设为false,避免误触发提示
  • iOS的导航栏返回按钮会被Shell的Navigating事件拦截,无需额外处理
  • 侧边菜单、Tab切换的导航动作都会被Shell全局事件覆盖,无需单独编写逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 18:32:40