Dela via


Quickstart: Navigating between pages (XAML)

[This article is for Windows 8.x and Windows Phone 8.x developers writing Windows Runtime apps. If you’re developing for Windows 10, see the latest documentation]

This topic discusses basic navigation concepts and demonstrates how to create an app that navigates between two pages.

For help choosing the best navigation pattern for your app, see Navigation patterns.

See the Flat navigation and Hierarchical navigation patterns in action as part of our App features, start to finish series.

Roadmap: How does this topic relate to others? See:

You can create multiple pages for your app and support the user navigating between the pages within the app, similar to how you navigate through pages on a single website. Microsoft Visual Studio has page templates that provide basic navigation support for Windows Runtime apps using C# or Microsoft Visual Basic. In this topic, we use the page templates to create a simple app that supports navigation.

Note  

When we discuss navigation for Windows Runtime apps, we mean navigating between pages within an app, not navigating between apps.

 

Prerequisites

This topic assumes that you can create a basic Windows Runtime app using C# or Visual Basic. For instructions on creating your first Windows Runtime app, see Create your first Windows Runtime app using C# or Visual Basic.

Creating the navigation app

Creating the blank app

  1. On the Visual Studio menu, choose File > New Project.

  2. In the left pane of the New Project dialog box, choose the Visual C#, Visual Basic, or Visual C++ node.

  3. In the center pane, choose Blank App.

  4. In the Name box, enter BlankApp, and then choose the OK button.

    The solution is created and the project files appear in Solution Explorer. For more info about the project files, see C#, VB, and C++ project templates for Windows Runtime apps.

    Important  When you run Visual Studio for the first time, it prompts you to obtain a developer license. For more info, see Get a developer license.

     

  5. To run the program, on the Visual Studio menu, choose Debug > Start Debugging, or press F5.

    A blank page is displayed.

  6. Press Shift+F5 to stop debugging and return to Visual Studio.

Next, add two pages to the project. These act as the pages we navigate between. Do the following steps two times to add two pages.

Adding the basic page

  1. In Solution Explorer, open the shortcut menu for the BlankApp project node, and then choose Add > New Item.
  2. In the Add New Item dialog box, choose Blank Page in the middle pane.
  3. In the Name box, enter page1 (or page2) and choose the Add button.

After you have done the previous steps two times, the following files should have been added to your project.

  • BasicPage1.xaml
  • BasicPage1.xaml.cs or BasicPage1.xaml.vb
  • BasicPage2.xaml
  • BasicPage2.xaml.cs or BasicPage2.xaml.vb

Now we need to use the pages we added in the app. Make the following changes to BasicPage1.xaml.

  • Find the TextBlock element named pageTitle and change the Text property to Page 1. The XAML should look like this (the "..." represents other attributes you aren't changing):

    <TextBlock x:Name="pageTitle" Text="Page 1" .../>
    
  • Add the following XAML as a second child element to the root Grid. The StackPanel element should be a sibling to the Grid that contains the back button and page title.

    <StackPanel Grid.Row="1"
                Margin="120,0,120,60">
        <HyperlinkButton Content="Click to go to page 2" Click="HyperlinkButton_Click"/>
    </StackPanel>
    

Make the following changes to BasicPage2.xaml.

  • Find the TextBlock element named pageTitle and change the Text property to Page 2. The XAML should look like this:

    <TextBlock x:Name="pageTitle" Grid.Column="1" Text="Page 2" 
               Style="{StaticResource PageHeaderTextStyle}"/>
    
  • Add the following XAML as a second child element to the root Grid. The StackPanel element should be a sibling to the Grid that contains the back button and page title.

    <StackPanel Grid.Row="1"
                Margin="120,0,120,60">
        <TextBlock HorizontalAlignment="Left" Name="tb1" Text="Hello World!"/>
    </StackPanel>
    

Add the following code to the BasicPage1 class in BasicPage1.xaml.cs or BasicPage1.xaml.vb.

private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
    this.Frame.Navigate(typeof(BasicPage2));
}
Private Sub HyperlinkButton_Click(sender As Object, e As RoutedEventArgs)
    Me.Frame.Navigate(GetType(BasicPage2))
End Sub 

Now that we've prepared the new pages, we need to make BasicPage1 the first thing that appears when the app starts. Open app.xaml.cs/vb and change the OnLaunched method to call Frame.Navigate by using BasicPage1 instead of BlankPage. The relevant line of code looks like this:

    if(!rootFrame.Navigate(typeof(BasicPage1), e.Arguments))
    { ... }
    If Not rootFrame.Navigate(GetType(BasicPage1), e.Arguments) Then
...

Note  The code here uses the return value of Navigate to throw an app exception if the navigation to the app's initial window frame fails. When Navigate returns true, the navigation happens.

 

Now you are ready to test the app. Start the app, and click the link that says Click to go to page 2. The second page should appear that says "Page 2" at the top. In a Windows Store app, notice that there is a back button to the left of the page title. Click the button to return to the first page. In a Windows Phone Store app, click the phone's Back button to return to the first page.

The Frame and Page classes

Before we add more functionality to our app, let's look at how the pages we added provide navigation support for the app.

The file App.xaml.cs/vb/cpp creates a Frame, if one doesn't already exist, and makes the Frame the content of the current Window. If the content of the frame is null, the app navigates to the home page as specified in the code behind App.xaml. For example, in the the Grid App, the code is rootFrame.Navigate(typeof(GroupedItemsPage), "AllGroups") ).

The Frame class is primarily responsible for navigation and implements methods such as Navigate, GoBack, and GoForward. You use the Navigate method to display content in the Frame. In the previous example, the App.OnLaunched method creates a Frame and passes BasicPage1 to the Navigate method. Then the method sets the content of the app's current window to the Frame. The result is that the app's window contains a Frame that contains BasicPage1

BasicPage1 is a subclass of the Page class. The Page class has a Frame property, a read-only property that gets the Frame that contains the Page. When the Click event handler of the HyperlinkButton calls Frame.Navigate(typeof(BasicPage2)), the Frame in the app's window displays the content of BasicPage2.

Suspension manager

Important  

The SuspensionManager helper class is provided in the following project templates:

Windows Apps Hub App, Grid App, Split App
Windows Phone Apps Hub App, Pivot App
Universal Apps Hub App

 

The SuspensionManager helper class is not provided with the Blank App templates.

 

During setup, SuspensionManager registers the Frame. SuspensionManager is a helper class provided in the Common folder in the template and provides the implementation used to store and load state when the app is terminated.

All apps move through an application lifecycle as dictated by the operating system. Whenever an app is terminated by the system for reasons such as resource constraints, shut down, reboot, and so forth, you as the developer must restore data upon resuming the app. SuspensionManager is provided to help you with this task.

SuspensionManager captures global session state to simplify process lifetime management for an application. Session state is automatically cleared under a variety of conditions and should be used only to store information that would be convenient to carry across sessions, but that should be discarded when an application crashes or is upgraded. This basically includes transient UI data.

SuspensionManager has two properties: SessionState and KnownTypes.

  • SessionState provides access to global session state for the current session. This state is serialized by the SaveAsync method and is restored by the RestoreAsync method. All data is saved and restored using DataContractSerialization and should be as compact as possible. Strings are other self-contained data types are strongly recommended.
  • KnownTypes stores a list of custom types provided to the DataContractSerializer that is used by the SaveAsync and RestoreAsync methods when reading and writing session state. Initially empty, additional types may be added to customize the serialization process.

SuspensionManager stores state in a dictionary, SessionState. The dictionary stores FrameState against a key that is uniquely bound to a Frame. Each FrameState dictionary holds state for each page in the navigation state for that particular frame. Each page stores the navigation parameter as well as any other state that the user decides to add.

Here is how that works: When a Frame is created, if you want the state to be stored for that frame it should immediately be registered. They are registered with the following call (SuspensionManager.RegisterFrame(rootFrame, "AppFrame")). Each frame should have a unique key associated with it. Generally most apps will only have a single frame. If you declare a second frame, it'll need to be registered as well. When a frame is registered, two attached properties are set on the frame. First is the key that you have associated with the frame, and second is the dictionary of session state that will be associated with the frame. Frames that have been previously registered will immediately have their navigation and state restored. Frames can be unregistered as well; all navigation state and history will be discarded.

And now for the important calls: SaveAsync and RestoreAsync. SaveAsync is used to save the entire SessionState. All frames that have been registered via SuspensionManager.RegisterFrame will also preserve their current navigation stack, which in turn gives their active page an opportunity to save its data. The SessionState is then serialized using a DataContractSerializer and written to a file stored in the local folder as defined by the ApplicationData.

RestoreAsync is used to read in the previously saved SessionState. All frames that have been registered with RegisterFrame will also restore their prior navigation state, which will give their active page an opportunity to restore its state. Again as in SaveAsync, a DataContractSerializer is used to de-serialize the state stored in a file in the Application’s local folder.

There are two common errors that people hit when attempting to store the state of their app.

  • The types stored by individual pages must be able to be serialized by the DataContractSerializer in C# and VB. To do this any custom type must be registered before it can be saved or restored. SuspensionManager provides the KnownTypes collection which passes the types in the collection to the DataContractSerializer. As the SuspensionManager is called to restore state in the OnLaunched override of the code behind for App.xaml, a good place to register types is in the app constructor.

            public App()
            {
                this.InitializeComponent();
                this.Suspending += OnSuspending;
                SuspensionManager.KnownTypes.Add(typeof(MyCustomType));
            }
    
  • The parameters passed in using navigation must be able to be serialized by the platform. When we are saving and restoring the navigation stack, we call Frame.GetNavigationState() and Frame.SetNavigationState(). Both of these calls make use of an internal serialization format and all types passed as the parameter in Frame.Navigate() must be able to be serialized by the platform.

The use of SuspensionManager is wrapped in the implementation of NavigationHelper.

NavigationHelper is an implementation of a page that provides the following important conveniences:

  • Event handlers for Navigate, GoBack, and GoForward.
  • Mouse and keyboard shortcuts for navigation.
  • State management for navigation and process lifetime management.

In addition to providing the implementations described, NavigationHelper also needs to be called from the OnNavigatedTo() and OnNavigatedFrom() event handlers that are implemented on each page. When these events occur, NavigationHelper calls a page-specific implementation of LoadState() and SaveState(). You can customize the implementation of these functions on each page. They should be used in place of OnNavigatedTo() and OnNavigatedFrom() respectively.

Note  For Windows Phone Store apps, OnNavigatedFrom() is called when the app is suspended. OnNavigatedTo() is not called when the app is resumed.

OnNavigatedFrom() is called when the page is about to be displayed in a Frame. When we are navigating to a new page we load state associated with the page. If the page is being restored, the state that was previously saved for the page is restored. LoadState is then called such that each page can react. LoadState has two parameters; the original navigation parameter passed into OnNavigatedTo and the previous page state if it exists.

OnNavigatedFrom() is called when the page is no longer going to be displayed in a Frame. When we are navigating away from a page, we allow the page to save its current state. An empty dictionary is passed into SaveState(). Each page can override SaveState and store objects in the keyed dictionary (string to object). This dictionary is then associated with the page and added to the SessionState that SuspensionManager keeps track of for the given frame.

Note  

  • Any data that is stored in the individual page must be available to be serialized by the DataContractSerializer.
  • It is also important to store only transient UI information here, because this state will be lost if the app is closed by any means other than Terminated.

 

When we created the navigation pages, we used the Basic Page template. This template, and other templates that support navigation, creates a page that provides a Back button in the top left corner of the page. The button is styled to be visible only when the button is enabled. This is why you don't see the Back button on the first page but you see it on the second page.

The following page templates offer this same navigation support.

  • Basic Page
  • Group Detail Page
  • Grouped Items Page
  • Item Detail Page
  • Items Page
  • Split Page
  • Hub Page
  • Search Results Page

Passing information between pages

Our app navigates between two pages, but it really doesn't do anything interesting yet. Often, when an app has multiple pages, the pages need to share information. Let's pass some information from the first page to the second page.

In BasicPage1.xaml, replace the StackPanel that you added earlier with this XAML.

<StackPanel Grid.Row="1"
    Margin="120,0,120,60">
    <TextBlock Text="Enter your name"/>
    <TextBox Width="200" HorizontalAlignment="Left" Name="tb1"/>
    <HyperlinkButton Content="Click to go to page 2" Click="HyperlinkButton_Click"/>
</StackPanel>

In BasicPage1.xaml.cs or BasicPage1.xaml.vb, replace the HyperlinkButton_Click event handler with the following code.

private void HyperlinkButton_Click(object sender, RoutedEventArgs e)
{
    this.Frame.Navigate(typeof(BasicPage2), tb1.Text);
}
    Private Sub HyperlinkButton_Click(sender As Object, e As RoutedEventArgs)

        Me.Frame.Navigate(GetType(BasicPage2), tb1.Text)

    End Sub
    

In BasicPage2.xaml.cs or BasicPage2.xaml.vb, fill in the empty navigationHelper_LoadState method with this:

private void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
    string name = e.NavigationParameter as string;

    if (!string.IsNullOrWhiteSpace(name))
    {
        tb1.Text = "Hello, " + name;
    }
    else
    {
        tb1.Text = "Name is required.  Go back and enter a name.";
    }
}
    Private Sub navigationHelper_LoadState((e As NavigationHelper.LoadStateEventArgs)
        Dim name As String = TryCast(e.NavigationParameter, String)
        If Not String.IsNullOrWhiteSpace(name) Then
            tb1.Text = "Hello, " & name
        Else
            tb1.Text = "Name is required.  Go back and enter a name."
        End If
    End Sub

Run the app, type your name in the text box, and then click the link that says Click to go to page 2. When you called this.Frame.Navigate(typeof(BasicPage2), tb1.Text); in the Click event of the HyperlinkButton, the tb1.Text property is passed when BasicPage2 loads. Then, the navigationHelper_LoadState method of BlankPage2 gets the value from the event data and uses it to display a message.

Caching a page

When you ran the last example, you might have noticed that if you click the Back button on BasicPage2, the TextBox on BasicPage1 is empty when it appears. Let's suppose that the user of the app wants to go back and make a change on the previous page. If BasicPage1 had many fields to fill in, the user would not be happy to see reset fields when the app went back to that page. You can specify that a page be cached by using the NavigationCacheMode property. In the constructor of BasicPage1, set NavigationCacheMode to Enabled.

public BasicPage1()
{
    this.InitializeComponent();
    ...
    this.NavigationCacheMode = 
        Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
}
Sub New()
    InitializeComponent()
    ...
    Me.NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled
End Sub

Now when you run the app and navigate from BasicPage2 back to BasicPage1, the TextBox on BasicPage1 retains its value.

Summary

In this topic you learned how to create a simple app that navigates between pages. You learned how to pass information from one page to another and also how to specify that a page's state should be cached.

Next steps

For a complete sample that uses many of the Page and Frame features together, see XAML Navigation sample. The sample includes features not discussed here, including:

Navigating between pages

For designers

Navigation patterns

Command patterns

Layout

Back button

Guidelines for the hub control

Guidelines for app bars (Windows Runtime apps)

Making the app bar accessible

For developers (XAML)

Windows.UI.Xaml.Controls Hub class

Windows.UI.Xaml.Controls AppBar class

Windows.UI.Xaml.Controls CommandBar class

Your first app - Part 3: Navigation, layout, and views

Your first app - Add navigation and views in a C++ Windows Store app (tutorial 3 of 4)

XAML Hub control sample

XAML AppBar control sample

XAML Navigation sample

Adding app bars (XAML)