Handling the Back Button in Windows 10 UWP Apps

The cool thing about Universal Windows Platform (UWP) apps is that they run on an assortment of devices, from PCs, tablets, and phones to (soon) Xboxes and HoloLens, among others. Personally, I can’t wait to see some of the apps I’ve written light up on my kids’ Xbox. They’ll think I’m a hero (“my dad writes Xbox apps!”) even though I’m not.

But as every hero knows, with great power comes great responsibility. One of the issues you’ll run into when writing a UWP app is how to handle the Back button. Windows phones have Back buttons, but other devices don’t. One way to handle the Back button on phones is to add a reference to Microsoft’s Mobile Extension SDK and write adaptive code that responds to HardwareButtons.BackPressed events, as I wrote about in a previous post. Of course, that doesn’t solve the problem of allowing users to navigate backward on devices that lack Back buttons. Which is why Microsoft introduced the Windows.UI.Core.SystemNavigationManager class. SystemNavigationManager does two important things for you:

  • Upon request, it displays a software Back button when your app is running on a device without a Back button
  • It allows you to handle clicks of the Back button (software or hardware) without adding extension SDKs and without writing adaptive code

Here’s what Contoso Cookbook looks like on a PC with a SystemNavigationManager-provided Back button:

Cookbook

Making the Back button appear requires just one line of code:

SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;

Responding to clicks of the Back button is a simple matter of wiring up a handler for SystemNavigationManager.BackRequested events:

SystemNavigationManager.GetForCurrentView().BackRequested += (s, e) =>
{
    // TODO: Go back to the previous page
};

The beauty of it is that this code works without change on phones and other devices. SystemNavigationManager is smart enough not to display a software Back button on devices that have Back buttons, and to fire BackRequested events when the user clicks the software Back button provided by SystemNavigationManager or taps the hardware Back button on a phone.

So far, so good. But here’s where it gets interesting. How do you leverage SystemNavigationManager in a multipage app without adding SystemNavigationManager code to every page? Is there a way, for example, to centralize the Back-button code so that it “just works” independent of how many pages the app has or the content of those pages?

The answer is a resounding yes. In fact, there’s a pattern I use in the UWP apps I write that isolates all the SystemNavigationManager code in App.xaml.cs and works exactly as you’d expect it to. The Back button appears whenever the backstack contains a page to go back to, and disappears when it does not. All you have to do is add a few lines of code to the code already in App.xaml.cs. Here’s a stock App.xaml.cs file created by Visual Studio (minus some of the extraneous stuff VS includes), with the code added to handle the Back button highlighted in red:

sealed partial class App : Application
{
    public App()
    {
        this.InitializeComponent();
        this.Suspending += OnSuspending;
    }

    protected override void OnLaunched(LaunchActivatedEventArgs e)
    {
        Frame rootFrame = Window.Current.Content as Frame;

        // Do not repeat app initialization when the Window already has content,
        // just ensure that the window is active
        if (rootFrame == null)
        {
            // Create a Frame to act as the navigation context and navigate to the first page
            rootFrame = new Frame();

            rootFrame.NavigationFailed += OnNavigationFailed;
            rootFrame.Navigated += OnNavigated;

            if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
            {
                // TODO: Load state from previously suspended application
            }

            // Place the frame in the current Window
            Window.Current.Content = rootFrame;

            // Register a handler for BackRequested events and set the
            // visibility of the Back button
            SystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested;

            SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
                rootFrame.CanGoBack  ?
                AppViewBackButtonVisibility.Visible :
                AppViewBackButtonVisibility.Collapsed;
        }

        if (rootFrame.Content == null)
        {
            // When the navigation stack isn't restored navigate to the first page,
            // configuring the new page by passing required information as a navigation
            // parameter
            rootFrame.Navigate(typeof(MainPage), e.Arguments);
        }

        // Ensure the current window is active
        Window.Current.Activate();
    }

    void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
    {
        throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
    }

    private void OnNavigated(object sender, NavigationEventArgs e)
    {
        // Each time a navigation event occurs, update the Back button's visibility
        SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
            ((Frame)sender).CanGoBack ?
            AppViewBackButtonVisibility.Visible :
            AppViewBackButtonVisibility.Collapsed;
    }

    private void OnSuspending(object sender, SuspendingEventArgs e)
    {
        var deferral = e.SuspendingOperation.GetDeferral();
        // TODO: Save application state and stop any background activity
        deferral.Complete();
    }

    private void OnBackRequested(object sender, BackRequestedEventArgs e)
    {
        Frame rootFrame = Window.Current.Content as Frame;

        if (rootFrame.CanGoBack)
        {
            e.Handled = true;
            rootFrame.GoBack();
        }
    }
}

Plug these lines into App.xaml.cs and you, too, can achieve Back-button bliss in UWP apps!

Stay Informed

Sign up for the latest blogs, events, and insights.

We deliver solutions that accelerate the value of Azure.
Ready to experience the full power of Microsoft Azure?