I'm Andrew Hoefling, and I work for FileOnQ as a Lead Software Engineer building mobile technologies for Government, Financial and First Responders using Xamarin. 

 

Uno Platform View Stack Navigation


The Uno Platform Getting Started blog series is a blog series that I put together for October of 2020. It contains several articles that will help you get started building scalable enterprise applications in Uno Platform. Be sure to checkout all the blogs in the series by heading to the 1st article - Uno Platform Getting Started Series

Uno Platform creates a WinUI bridge to build cross-platform applications for Windows, iOS, Android and Web Assembly. Each platform has a different technique for handling navigation. Using the UWP specification you can easily create a View Statck style of navigation that has a consistent look and feel across the different platforms.

View Stack

A View Stack Navigation is one of the most basic navigation models in application design. As the user navigates from one page to the next a new page is placed on top of the other. When the user navigates back, the app will go back to the page they were at last. 

(image provided by Microsoft Docs)

To learn more about different navigation design patterns in UWP application development, check out the UWP Navigation Documentation.

Described in a more technical manner, View Stack Navigation utilizes the Stack Data Structure, which opperates in a First In Last Out data structure. This means the last item added to the Stack will be the first item removed. In a View Stack, as you navigate back to the previous page your remove the current view from the stack.

Uno Platform Navigation

When you first load your Uno Platform application, it uses the default navigation and arguments to tell the system to load your MainPage.

rootFrame.Navigate(typeof(MainPage), e.Arguments);

When you need to Navigate to other pages you will use the exact same technique. In our current example when the application launches the MainPage is displayed. Given the following XAML we have a button that will eventually Navigate the user to a new page.

<Page
    x:Class="Uno.Samples.Navigation.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Uno.Samples.Navigation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
		<TextBlock Text="Hello, world!" Margin="20" FontSize="30"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Center"/>
        <Button Content="Go to Second Page"
                VerticalAlignment="Bottom"
                HorizontalAlignment="Center"
                Click="Button_Click"/>
    </Grid>
</Page>

Create SecondPage to Navigate To

Before we can Navigate to a new page we need to create it. Create a simple empty Blank Page called SecondPage. Below is the xaml for our new page.

<Page
    x:Class="Uno.Samples.Navigation.SecondPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Uno.Samples.Navigation.Shared"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <TextBlock Text="Second Page"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Center"/>
    </Grid>
</Page>

Perform Navigation 

In the Code Behind MainPage.xaml.cs you will invoke the command to navigate the application to your new page. Earlier when we defined out Button in the MainPage we configured an Event Listener to handle the click events. Now we will implement the logic to Navigate to the SecondPage.

private void Button_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(SecondPage));
}

Navigation Arguments

You may have noticed in the App.xaml.cs the default implementation utilizes the application launch arguments. These arguments can then be handled in the page that is loaded. This same technique can be used across any Page that the application loads. 

Consider you want to display custom content depending on user selection, such as a user selecting an item from a list. You can handle the user input in your new page to render the content slightly differently. This is common when you need to pass properties from one page to another.

The UWP specification allows you to pass any .NET Object in the Navigation specification. Let's pass a simple string message and render it to the screen.

Create the UI

First create our MessagePage which will have 1 TextBlock which will render the message sent from the MainPage.

MessagePage

<Page
    x:Class="Uno.Samples.Navigation.MessagePage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Uno.Samples.Navigation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <TextBlock x:Name="Message"
                   VerticalAlignment="Center"
                   HorizontalAlignment="Center" />
    </Grid>

</Page>

Let's update the MainPage to take user input that can then be passed to the new MessagePage.

MainPage

<Page
    x:Class="Uno.Samples.Navigation.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Uno.Samples.Navigation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel VerticalAlignment="Center"
                    HorizontalAlignment="Center"
                    Spacing="20">
            <TextBlock Text="Enter your message:" />
            <TextBox x:Name="InputMessage" />
            <Button Content="Send Message to Message Page"
                    Click="Button_Click"/>
        </StackPanel>
    </Grid>
</Page>

Navigate to MessagePage

In the MainPage open the code behind so we can implement the navigation logic. The method needs to implement the following rules to complete the navigation correctly:

  1. Retrieve the text content of the TextBox input field
  2. Navigate to MessagePage and add the text content as an argument

private void Button_Click(object sender, RoutedEventArgs e)
{
    // The InputMessage is declared in the MainPage.xaml
    Frame.Navigate(typeof(SecondPage), InputMessage.Text);
}

Handle Navigation in MessagePage

At this point the navigation will occur but the view will not update with the correct content as it needs to be handled in the MessagePage. All Page objects have a virtual methods that listens for different navigation events. In our MessagePage you will just override the navigation method and implement our logic there

  • OnNavigatedFrom
  • OnNavigatedTo
  • OnNavigatedFrom

When your page needs to handle navigation arguments, you will use OnNavigatedTo which is invoked right after the page is loaded. Update the MessagePage to include the following implementation of OnNavigatedTo

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    Message.Text = (string)e.Parameter;
}

This is the most basic way to handle the parameters, but I recommend adding additional checks to certify that the parameters are passed correctly. You do not want your app to crash because of a bad parameter data or no parameter data included in the navigation method.

Simply add a type check prior to updating the TextBlock :

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    if (e.Parameter is string myMessage)
        Message.Text = myMessage;
}

 Full MessagePage.xaml.cs code:

public sealed partial class MessagePage : Page
{
    public MessagePage()
    {
        this.InitializeComponent();
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);

        if (e.Parameter is string myMessage)
            Message.Text = myMessage;
    }
}

Navigation Animations

Up until this point our projects have been using the default animation behaviors built into Uno Platform. There are 3 major animation techniques you can use when navigating pages.

  • EntranceNavigationTransitionInfo - Explicitly play the page refresh animation
  • DrillInNavigationTransitionInfo - Play the drill in animation
  • SuppressNavigationTransitionInfo - Suppress the default animation

To specify your animation when navigating simply create a new instance of one of the objects listed above. 

private void Button_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(SecondPage), null, new EntranceNavigationTransitionInfo());
}

If you have no arguments to pass to the page, you will need to explicilty pass null.

Hide Animation

The most common case for me to use this API is to hide animations. If you are building complicated navigation designs hiding the animations can be valuable. 

private void Button_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(SecondPage), null, new SuppressNavigationTransitionInfo());
}

Go Back Navigation

As your user navigates through the app they will need to be able to pop the current view off of the View Stack, in other words a simple back button. There are 2 APIs available that you will want to use to handle popping the view off the Navigation Stack

  • CanGoBack() - Returns true if the app can navigate back. Useful for checking app state
  • GoBack() - Navigates the user back to the previous page

MainPage.xaml

<Page
    x:Class="Uno.Samples.Navigation.GoBackNavigation.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <Button Content="Go Back"
                Click="Button_Click" />
    </Grid>
</Page>

When the user taps on the button, we need to check if they can navigate back and then perform the navigation action.

private void Button_Click(object sender, RoutedEventArgs e)
{
    if (Frame.CanGoBack)
        Frame.GoBack();
}

Conclusion

Navigation starts as a simple topic and can spiral into very complex scenarios. When I was writing this article realized how complicated it can be to explain a basic View Stack navigation pattern. You should be able to take the samples here to get started with basic navigation in Uno Platform applications.

If you need a closer look at the different techniques, check out the sample code

-Happy Coding


Share

Tags

iOSAndroidUWPWASMWeb AssemblyNavigation