Wintellect Blogs

Handling the Back Button in Windows 10 UWP Apps

30 Jun , 2015  

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!

,


  • One question I have on this implementation… how does the Windows Mobile form factor deal with the Back Button being pressed on the *top level* page? I.e. where it should *normally* exit the app. I’ve seen some weirdness in this area after implementing this code… Full disclosure, I’m using Template10 from Jerry Nixon (https://github.com/Windows-XAML/Template10) which wraps this behavior.

    • Owen Johnson

      It ties into the OS’s back button. The one next to the start button that’s a hardware button on some phones. The interesting part is that there is no visual indication of what will happen when you press that button.

  • djkpA

    Thanks Wintellect for such a nice blog.This helped me alot.
    But I need restrict the back button functionality to goback again to Login page after the user login into my app. How to handle this?

    • kavimukil

      When navigating away from Login page remove its page stack entry.
      eg : this.Frame.BackStack.Remove(this.Frame.BackStack.LastOrDefault());

      • Attila Balogh

        Where I need to put this?
        I tried in different location. Can u tell me exactly, please?

      • kavimukil

        Add these line in your login page onnavigating from method.

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
        this.Frame.BackStack.Remove(this.Frame.BackStack.LastOrDefault());
        }

  • Don’t forget to remove handler when navigate from the previous page ! Without this, SystemNavigationManager will go back many times

  • Pingback: Taming the SplitView Control in Windows 10 – Wintellect DevCenter()

  • Brian Stewart

    Perfect thanks!
    I was stuck but you have helped me greatly with this
    thanks again

  • This is great, EXCEPT when I use this in conjunction with a splitview menu, when navigating back the SELECTED item in the splitview doesn’t change to match the page I have gone back to. Any solution for this?

    • spartan1047

      Hi, Do you find the solution of your problem?, I actually have the same problem and i dont know how to deal with it.

  • Arda

    How can i use this back button for webview ? This one works for frames(pages).

  • Nathan Bayles

    Thanks for posting this example. It was really helpful to see the diff of what I was adding.

  • Markus

    This is great solution, but WHAT IF in some specific page I want to show a back button confirmation dialog?

    • mudbox

      I solved this by simply return from OnBackRequested (in App.xaml.cs) when the page is a specific type that I want to handle differently:

      if (rootFrame.SourcePageType == typeof(GamePage))
      return;

      Then in “GamePage.xaml.cs” I subscribed to BackRequested and handled it:

      private void OnBackRequested(object sender, BackRequestedEventArgs e)
      {
      e.Handled = true;
      Pause();
      }

  • Hoby Mohamed

    thank you very much !

  • Isabelle Z

    This is a great way to handle the Back button; but I must miss something because it does’nt work on a desktop. In method OnBackRequested () rootFrame.GoBack is always false, so it never goes back. Where am I wrong? Is there something else to do ? Please help me 🙂

  • Cleber Matheus Andrade Silva

    And how it would look if it were done in C++?

  • Pingback: Windows 10 resources | .NET Junkyard()

  • Vicente Zambrano

    Thanks, very useful.

  • Priom Biswas

    My app doesn’t showing back button, what’s the problem? Can you put the source code please?

    • Angel HG

      where you put the first 2 codes of ths blog?

  • Angel HG

    Thanks!! so helpful 😉

  • Where put SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
    in app.xaml.cs or MainPage.xaml.cs public mainPage() …

  • Faran Rasheed

    Thank u so much 🙂

  • Hi! Great post but what if I want to use the backbutton to navigate from view to view but use it as a simple goback button when a webview is active?

  • Pedro Machado

    Nice post. Good information that helped me.

  • Martin Jul Hammer

    This just works! Thank you so much!

  • Great tip! Thanks a lot!

  • Umair Jameel

    This is one of most amazing tutorial i have found. I have seen another which shows some more interesting points as well. Have a look at that.
    http://www.top5solutions.com/page-navigation-uwp-tutorial/

  • kunal arora

    A user opens app, logs in with his credentials, closes the application, now again when the user opens the app he/she should already be signed in. Can someone please help me with this ? How to keep user signed in ? Any help would be appreciated. Thanks in advance.

  • ThisWillDoIt

    Thank you.

  • Julie Curtis

    Not sure if this page is still ‘live’ but i’ll try anyway

    I’ve used your code and it works beautifully … thank you! But, I have one page where instead of navigating to a new page (and having to save state etc,) I simply use a two grids and a z-Index. This works very effectively Except … when showing Grid 2 it would be helpful to ‘Switch Off’ the Title-bar back button and then re-enable it when the user has returned (via a button on the page) to Grid 1. Is there a simple way of doing this ? please please please say Yes 🙂

  • Julie Curtis

    Ha! As you were … I figured it out

    (I really should read the whole article fist before asking dumb questions)