Saturday, 8 July 2017

Navigation 03 Shell back button

Previously we created a simple two page application that leverages the "SystemNavigationManager" and a simple button, however UWP's come with the option of a shell button for desktop mode; in tablet mode and phone you'll always have a back button and the SystemNavigationManager handles back for both of them, but in desktop it's your choice.

Let's choose to have the shell button appear.

Since our first page doesn't need a back button let's focus on our SecondPage.xaml.

<Page
    x:Class="pc.NavigateExample.SecondPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
            <TextBlock>Second Page</TextBlock>
            <TextBox x:Name="output_TextBox" PlaceholderText="Parameter received" />
            <Button x:Name="Back_Button" Click="Back_Button_Click">Back</Button>
        </StackPanel>
    </Grid>

</Page>

nothing new for the XAML, now let's make some changes to our codebehind

using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;

namespace pc.NavigateExample
{
    public sealed partial class SecondPage : Page
    {
        public SecondPage() {
            this.InitializeComponent();

            SystemNavigationManager.GetForCurrentView().BackRequested +=
                SecondPage_BackRequested;
        }

        protected override void OnNavigatedTo(NavigationEventArgs e) {
            var parameter = e.Parameter as string;

            if (parameter != null)
                output_TextBox.Text = parameter;

            if (Frame.CanGoBack)
                SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
                     AppViewBackButtonVisibility.Visible;
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            base.OnNavigatedFrom(e);
            SystemNavigationManager.GetForCurrentView().BackRequested -=
                SecondPage_BackRequested;
        }

        private void SecondPage_BackRequested(object sender, BackRequestedEventArgs e){
          if(Frame.CanGoBack && (e == null || !e.Handled ))
            Frame.GoBack();
        }

        private void Back_Button_Click(object sender, RoutedEventArgs e)
        {
            SecondPage_BackRequested(sender, null);
        }
    }
}


notice that in our OnNavigated to we check if our frame can go back, and if that's the case then we show our button. we have to do this in OnNavigatedTo, because the shell isn't ready in the constrictor (I think). Now since we implemented the SystemNavigationManager's back requested event handler we're golden just clicking the back button in the shell and we're off to the races.