Visually Located

XAML and GIS

Performing an async operation in the OnBackKeyPress method and still exit your Windows Phone apps

The OnBackKeyPress method allows you to perform special logic when the user presses the phone back button. You usually override this method when you do not want the user to actually go back a page. An example of this is if you show a popup, when the user presses the back button you should close the popup.

protected override void OnBackKeyPress(CancelEventArgs e)
{
    base.OnBackKeyPress(e);
 
    if (PopupIsOpen())
    {
        e.Cancel = true;
        ClosePopup();
    }
}

This workflow works great because everything is synchronous.

You may have seen some apps that prompt you with a MessageBox asking if you want to exit. If you say yes the app exits and if you say no, you do not exit the app.

protected override void OnBackKeyPress(CancelEventArgs e)
{
    base.OnBackKeyPress(e);
    var result = MessageBox.Show(
        "Are you sure you want to exit?", "Exit app?", MessageBoxButton.OKCancel);
    if(result == MessageBoxResult.Cancel)
    {
        e.Cancel = true;
    }
}

This also works because the built in MessageBox suspends code execution when the Show method is called. This does not work when you are need to perform an async operation. An example of this is when you create a ShowAsync method for the Windows Phone Toolkit CustomMessageBox. Another example is calling to a service to save some settings. You would want to let the user know if you were unable to save.

protected async override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
    base.OnBackKeyPress(e);
 
    Microsoft.Phone.Controls.CustomMessageBox msgBox = new CustomMessageBox();
    msgBox.RightButtonContent = "yes";
    msgBox.LeftButtonContent = "no";
    msgBox.Caption = "Are you sure you want to exit the app?";
    msgBox.Title = "Exit app?";
    var result = await msgBox.ShowAsync();
    
    // right button is cancel button
    if (result == CustomMessageBoxResult.RightButton)
    {
        e.Cancel = true;
    }
}

NOTE: I in no way indorse or support the use of message boxes when exiting the app. This is used merely as an example

When the CustomMessageBox is shown, the method is exited. This is the power of async/await. As soon as the async method happens, the method will exit, and as such, the app will exit. You will need to change your approach here. The first thing is to set e.Cancel to true before the async method call. This will stop the app from exiting, but as I mentioned you will be unable to set it back to true. You will have to manually exit the app. This is done in one of two ways, if you are using Windows Phone 7, you can reference the Microsoft.Xna.Framework.Game assembly and use the Exit method of the Game class.

new Microsoft.Xna.Framework.Game().Exit();

If you are using Windows Phone 8, you can use the new Terminate method  of the Application class.

Application.Current.Terminate();

Wrapping it all up your OnBackKeyPress method looks like

protected async override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
{
    base.OnBackKeyPress(e);
    e.Cancel = true;
 
    Microsoft.Phone.Controls.CustomMessageBox msgBox = new CustomMessageBox();
    msgBox.RightButtonContent = "yes";
    msgBox.LeftButtonContent = "no";
    msgBox.Caption = "Are you sure you want to exit the app?";
    msgBox.Title = "Exit app?";
    var result = await msgBox.ShowAsync();
    
    // left button is yes button
    if (result == CustomMessageBoxResult.LeftButton)
    {
        // if using WP7
        //new Microsoft.Xna.Framework.Game().Exit();
 
        //if using WP8
        Application.Current.Terminate();
    }
}

This approach works for any of your OnBackKeyPress methods, not just in the first page of your app. If you instead want to navigate backward, change that exits the app to:

NavigationService.GoBack();

blog comments powered by Disqus