App close confirmation in UWP

WinUI

6 years ago

It is a common request from app developers to be able to display a confirmation dialog when their app is being closed. Although this scenario is becoming less and less relevant in days of mobile apps and cloud-based data, it is still useful in specific cases. In this article we will learn how to implement this functionality in UWP apps.

API

Although Microsoft Edge browser had this functionality since the beginning, the app close confirmation API itself was made publicly available to app developers in Windows 10 Creators Update (15063) and requires declaration of a restricted capability. The key to the API is the SystemNavigationManagerPreview class in the Windows.UI.Core.Preview namespace. Similarly to many other UI-related APIs it is tied to an app window and the instance has to be retrieved from the UI thread using the GetForCurrentView() method. Then we must handle the CloseRequested event, which is executed when the app close button in the title bar is pressed. The best place to put this is after the app initialization in App.xaml.cs ideally just before the Window is activated:

SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += App_CloseRequested;
// Ensure the current window is active
Window.Current.Activate();

Implementing confirmation

The CloseRequested event has a SystemNavigationCloseRequestedPreviewEventArgs argument, which has a Handled property, which can be set to true if we want to cancel closing of the app. The catch is that most of the time we probably want to display some kind of dialog to confirm by the user, but such operation is inherently asynchronous and that means the event handler will terminate before the Handled property can be set. Luckily the event args object also provides the Deferral, which is the usual way similar situations are handled in UWP apps. At the beginning of the event handler we call GetDeferral method, which returns a deferral instance and tells the system to wait until Complete() method is called before it evaluates theHandled property.

private async void App_CloseRequested(object sender, SystemNavigationCloseRequestedPreviewEventArgs e)
{
    var deferral = e.GetDeferral();
    var dialog = new MessageDialog("Are you sure you want to exit?", "Exit");
    var confirmCommand = new UICommand("Yes");
    var cancelCommand = new UICommand("No");
    dialog.Commands.Add(confirmCommand);
    dialog.Commands.Add(cancelCommand);
    if (await dialog.ShowAsync() == cancelCommand)
    {
        //cancel close by handling the event
        e.Handled = true;
    }
    deferral.Complete();
}

Adding capability

Because the app close confirmation is a restricted capability, you have to explicitly declare it in your app's manifest. When your app is later certified in the Microsoft Store, the app close functionality will be manually tested to ensure you use it responsibly and don't just prevent users from closing your app. Let's right-click the Package.appxmanifest file in the Solution Explorer and choose View code. In the Pacakage element we add rescap namespace declaration and update IgnorableNamespaces attribute:

<Package ...
  xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
  IgnorableNamespaces="uap mp rescap">

Then we scroll down to the Capabilities section and declare the confirmAppClose capability:

<rescap:Capability Name="confirmAppClose" />

Now we can run and try to close the app. We should see the confirmation dialog and depending on the button you click the app should either stay open or close.

Source code

Example source code for this article is available on my GitHub.

Summary

We have implemented app close confirmation in UWP. Except for remembering to declare the capability in the app manifest it is pretty straightforward and even allows displaying confirmation UI in asynchronous manner.