When our UWP Application deal with user data in it, e.g. like drawings or documents, we usually want to make sure user won't close the App by accident and lose their work. Just like what you see in a Office application, it will ask you if you want to save your document before close the App.
For a long time, UWP could not do that in a normal way. Because it is not a general public API and it is still not well documented today. But there are some UWP Apps with this capibility like Microsoft's own "Paint 3D" App:
I did some research today and finally find a way to do this. Let me share with you.
1. Add Restricted API Capability
Open your Package.appxmanifest
file.
Add a namespace into Package
node:
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
In order to create App Package without error, we also need to ignore
the rescap namespace by adding it into IgnorableNamespaces
property in the Package
node:
IgnorableNamespaces="uap mp rescap genTemplate"
The Package
node will look like this:
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap mp rescap">
Then, in Capabilities
node, add:
<rescap:Capability Name="confirmAppClose"/>
The Capabilities
will look like this:
<Capabilities>
...
<rescap:Capability Name="confirmAppClose"/>
...
</Capabilities>
2. Handling Close App Action
The close app action can now be handled by a preview API:
Windows.UI.Core.Preview.SystemNavigationManagerPreview.GetForCurrentView().CloseRequested
For example, in your code, like MainPage.xaml.cs
, you can now use this API to detect if the user clicked "X" button and pop up the dialog like this:
public MainPage()
{
this.InitializeComponent();
Windows.UI.Core.Preview.SystemNavigationManagerPreview.GetForCurrentView().CloseRequested +=
async (sender, args) =>
{
args.Handled = true;
var result = await SaveConfirm.ShowAsync();
if (result == ContentDialogResult.Primary)
{
// Save work;
}
else
{
App.Current.Exit();
}
};
}
One thing to notice is that, args.Handeled
must be set to true, or your App will still close on clicking the "X" button.
Vincent
WoCao, you finally did it!!! Niubility!!!
Jay Heuer
Ahem, I am not able to find the namespace Windows.UI.Core.Preview.SystemNavigationManagerPreview. Anything I need to NuGet here?
Q2P0
Well post, thanks.
Maybe instead call "App.Current.Exit();" Will be better do "args.Handled = true;" Seems less agressive.
Andrian
I have a problem with SaveConfirm. Can't find this. Could you help?
David
Hi. Thanks for your code. I just want to share how I handled this snippet if the app uses multi-instance window (New View): https://pastebin.com/raw/k1brBcTK
Jelger
I'm trying to implement this for a Hololens app, but cannot get it to work so far. Any idea on if and how this could be done on Hololens?
Heiko
You must explain the reason for the usage to Microsoft if you want to publish such an app in the shop. But most of the time you will get a confirmation. But there's a stupid behavior by design: If the app is minimized, it won't be closed via the context menu until you restore the app.