[UWP]在应用退出时弹出确认提示框

1. 需求

在应用退出时(点击右上角的关闭按钮)弹出一个确认按钮可以说是一个最常见的操作了,例如记事本的“你是否保存”:

但这个功能在UWP上居然有点小复杂。这篇文章将解释如何实现这个功能。

2. CloseRequested

为了监视应用退出事件,我本来使用了CoreApplication.Exiting,但好像并不起作用,后来我就没再研究它的触发机制了。在Windows 10 Creators Update (15063)以后UWP提供了一个新的API:SystemNavigationManagerPreview.CloseRequested事件。这个事件会在用户点击窗体右上角的关闭按钮时触发,开发者可以在这个事件里处理保存数据、确认关闭等。最好在App.xaml.cs中的Window.Current.Activate();前后订阅这个事件。

Window.Current.Activate();

SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += (s, e) =>
{
    //DO STH
};

3. 弹出确认提示框

CloseRequested事件包含一个名为SystemNavigationCloseRequestedPreviewEventArgs的EventArgs(名字真是超级长),它包含一个Handled属性,如果要取消关闭事件,可以将Handled设置为Ture,这点和WPF很像。SystemNavigationCloseRequestedPreviewEventArgs还提供了GetDeferral函数,它返回一个Deferral对象,它可以在异步操作中延迟UWP应用生命周期事件的执行,知道调用它的Complete方法。配合异步的ContentDialog,具体代码如下:

Windows.UI.Core.Preview.SystemNavigationManagerPreview.GetForCurrentView().CloseRequested +=
async (sender, args) =>
{
    var deferral = args.GetDeferral();

    var messageDialog = new ContentDialog
    {
        Title = "记事本",
        Content = "你想要保存更改吗?",
        PrimaryButtonText = "保存",
        SecondaryButtonText = "不保存",
        CloseButtonText = "取消"
    };

    messageDialog.DefaultButton = ContentDialogButton.Primary;

    var result = await messageDialog.ShowAsync();
    switch (result)
    {
        case ContentDialogResult.None:
            args.Handled = true;
            break;
        case ContentDialogResult.Primary:
            await SaveDataAsync();
            break;
        case ContentDialogResult.Secondary:
            break;
        default:
            break;
    }

    deferral.Complete();
};

private async Task SaveDataAsync()
{

}

在上面的代码中,如果点击取消按钮,则将Handled设置为true以取消关闭。点击确认则保存数据再关闭应用。无论选择哪个,最后都需要调用Deferral.Complete。最终运行效果应该如下(讲真,ContentDialog真的丑):

4. 添加应用功能声明

有没有发现上面"最终运行效果应该如下"中的应该两字是粗体?因为这时候上面的代码还是没有效果。究其原因,是因为confirmAppClose是一个受限功能,必须修改应用程序包清单源文件(Package.appxmanifest), 添加xmlns: rescap XML 命名空间声明,并声明受限功能。

<?xml version="1.0" encoding="utf-8"?>
<Package
    ...
    xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
    IgnorableNamespaces="... rescap">
...
<Capabilities>
    <rescap:Capability Name="confirmAppClose"/>
</Capabilities>
</Package>

这样,在本地运行的时候,应用终于可以弹出确认提示框了。一旦使用了受限功能,应在提交应用到Microsoft Store的时候提供信息以便获得批准,有一些功能只在极其特殊和有限的情况下才获准在提交到 Microsoft Store 的应用中使用,幸好这里时候的confirmAppClose很容易通过。在提交选项里会出现受限的功能这一节,如实填写就可以了,中文也可以。

这样,所有工作都做了,确认提示框功能终于完成了。

5. 然而还有BUG

我们知道UWP的应用生命周期中,在background 运行和suspended状态时应用基本处于暂停状态,也不会处理UI功能,这时候让它弹框?“除非你叫醒我,否则我罢工”。所以在应用不可视的状态下关闭应用,例如最小化的情况下在任务栏点击关闭窗口,程序能怎么办?

弹框是不可能弹的,只能装死了。

所以这时候程序就完全没有反应。当应用重新回到前台运行,确认框才会弹出来。不过只是个小小的bug,我们可以选择原谅它:

6. 参考

应用功能声明 - UWP apps Microsoft Docs

App package manifest - Windows UWP applications Microsoft Docs

SystemNavigationManagerPreview.CloseRequested Event (Windows.UI.Core.Preview) - Windows UWP applications Microsoft Docs

Deferral Class (Windows.Foundation) - Windows UWP applications Microsoft Docs

Windows 10 UWP 应用生命周期 - UWP apps Microsoft Docs

原文地址:https://blog.51cto.com/14648815/2464059

时间: 2024-10-25 19:59:23

[UWP]在应用退出时弹出确认提示框的相关文章

删除文件时没有弹出确认提示框

存在的问题: 重装Win10系统后,发现通过右键删除文件和 Ctrl + D 快捷键来删除文件时,没有像之前一样弹出确认提示框了.原本习惯了删除文件后再从确认框中点击一下确认的,突然之间删除文件后它就直接进入了回收站.于是想着怎么解决,恢复从前... 解决方案: 进入回收站中,右键选择属性,弹出回收站属性窗口 2.对于想要删除文件时弹出确认提示框的磁盘,勾选显示删除确认对话框 桌面上的文件都是在C盘 原文地址:https://www.cnblogs.com/zhiyin1209/p/121501

js在关闭页面前弹出确认提示【转载】

最近项目中出现个bug,就是导出数据后,会提示确认导航,其实实际需求并不需要这个提示,可能是之前遗留的问题.查了下资料是在触发了onbeforeunload事件,那么剩下的就是代码组织问题了. 众所周知,现在的主流浏览器基本上都是多标签页的.在标签页数量较多的时候,可能连标签页的标题都无法看清.因此,用户可能一不小心就关错了标签 页,或者直接点击浏览器右上角的关闭按钮一不小心就关闭了所有标签页,而用户之前访问我们站点的某个页面可能还有非常重要的数据没有保存... 因此,在某些重要数据的录入页面,

解决PL/SQL Dev连接Oracle弹出空白提示框

第一次安装Oracle,装在虚拟机中,用PL/SQL Dev连接远程数据库的时候老是弹出空白提示框,网上找了很久,解决方法也很多,可是就是没法解决我这种情况的. 没办法,只能自己研究,经过大概一天时间吧,还是搞好了,写个总结. 出现这种问题,解决方法大概有这几种: 1.权限不够,导致弹出空吧提示框.(直接上链接) http://jingyan.baidu.com/article/066074d6760959c3c21cb0d6.html 就PL/SQL图标上点右键---属性---兼容性--管理员

用PHP实现弹出消息提示框

方法一: echo "<script>alert('提示内容')</script>"; 方法二: echo '<script language="JavaScript">;alert("这是";location.href="http://www.jinyuanbao.cn";</script>;'; 里面的location.href="index.htm"表示

Asp.Net后台弹出确认提示窗Confirm

前端js代码: function MyConfirm(message, guid) { if (confirm(message) == true) { document.getElementById("Hidden1").value = guid; } else { document.getElementById("Hidden1").value = ""; } //form1.submit(); form1.submit(); } 后台C#代码

bootstrap中使用modal加载kindeditor时弹出层文本框不能输入的问题

答案来自老外http://stackoverflow.com/questions/14795035/twitter-bootstrap-modal-blocks-text-input-field $('#myModal').on('shown', function() { $(document).off('focusin.modal'); }); 这个是国内同学的解决方法: http://www.oschina.net/question/226830_143869 //显示modal $('#m

cocos2dx 3.x(纯代码实现弹出对话框/提示框/警告框)

头文件: // //  PopAlertDialog.h //  macstudycocos2dx // //  Created by WangWei on 15/6/8. // // #ifndef __macstudycocos2dx__PopAlertDialog__ #define __macstudycocos2dx__PopAlertDialog__ #pragma once #include "cocos2d.h" #include "cocos-ext.h&q

关闭当前的子窗口,刷新父窗口,弹出层提示框

近期,在做后台的管理页面,为了有更好的用户体验,需要实现关闭当前页面,刷新父窗口,在网上查找方法,如下: JS代码如下: <script>  function refreshParent() {   window.opener.location.href = window.opener.location.href;   window.close(); } </script> html页面代码如下: <input type="button" id="

c# winform 弹出确认消息框判断是否删除?

1 if (MessageBox.Show("确认删除?", "此删除不可恢复", MessageBoxButtons.YesNo) == DialogResult.Yes) 2 { 3 4 ……………………………… 5 6 }