Random geekery since 2005.

Husband, father, programmer, speaker, writer, blogger, podcaster, collector, traveler, golfer.

31 Days of Windows 8 | Day #13: Navigation

Written in

by

This article is Day #13 in a series called 31 Days of Windows 8.  Each of the articles in this series will be published for both HTML5/JS and XAML/C#. You can find additional resources, downloads, and source code on our website.

advertisementsample4

We have spent the last few days getting pretty technical around updating the system with information to the let user know what’s going on.  In fact, in the first 12 days of this series, we’ve spent very little time talking about how to do one of the most common activities we’ll encounter in Windows 8 development: navigating between XAML pages.

Today, we’ll right that wrong by diving in to this subject.  There are three specific scenarios I want to make sure we cover in this article:

  • The simple act of navigation from Page A to Page B.  What happens when, and what information is available to us?
  • Passing data from one page to another.  This doesn’t just include strings and integers, we can also pass entire objects between pages.
  • Caching pages.  When a user clicks the back button, they don’t want to discover that all of the data they entered has disappeared.  We’ll discuss this more later.

Navigating Between Pages in Windows 8 XAML

It seems that every time we encounter a new platform, there’s also a new way to navigate between pages in a XAML application.  Windows 8 is no different in that regard.  This process is easily explained by walking you through creating some pages, so let’s start there.

Create a new Blank App Template, and then add two new Basic Page items to it.  For this example, you can call them PageA.xaml and PageB.xaml.

13-XAML-BasicPage

In each of those pages, there is a line of XAML that sets the AppName.

<Page.Resources>
    <x:String x:Key="AppName">My Application</x:String>
</Page.Resources>

 

Normally, we would move this to our App.xaml file, and let it apply to all of the pages in our application.  For today, we’re going to use this simple mechanism to give each of our pages a distinct name that we can see when it is loaded.  Set the value of PageA.xaml’s AppName to “Page A” and PageB.xaml’s AppName to “Page B” so that your pages look like this:

13-XAML-PageA 13-XAML-PageB

To make your sample easy to use, we’re also going to make a quick change to our App.xaml.cs file.  Near the bottom of the OnLaunched() method in App.xaml.cs is some code that looks like this:

if (rootFrame.Content == null)
{
    if (!rootFrame.Navigate(typeof(MainPage), args.Arguments))
    {
        throw new Exception("Failed to create initial page");
    }
}

You will want to change the reference from typeof(MainPage) to typeof(PageA).  Like this:

if (rootFrame.Content == null)
{
    if (!rootFrame.Navigate(typeof(PageA), args.Arguments))
    {
        throw new Exception("Failed to create initial page");
    }
}

This will cause your application to start up with the initial page being PageA.xaml.  At this point, go ahead and run your project.  You should see it start with the Splash Screen, and then PageA should load.  You should also notice that even though our preview in Visual Studio 2012 shows an arrow icon next to our page title, it is bound to whether or not the page is capable of “going back” with the Frame.CanGoBack property.  We’ll talk more about that a little later.

For now, let’s get to navigating.  You’ve technically already seen it in our App.xaml.cs file, but it looks a little different when you’re just going from page to page.  I’ve added a <Button> control to my PageA.xaml file, right before the <VisualStateManager> section.  The XAML for that looks like this:

<Button x:Name="PageBButton"
        Grid.Row="1"
        Content="To Page B"
        Width="150"
        Height="150"
        Click="PageBButton_Click" />

 

 

In the event handler for that <Button>, we write our first navigation statement (finally!)

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

 

 

As you can see, it’s a pretty simple process.  So let’s make it a little more complicated now, by adding a navigation button to Page B.  This might seem like a repetitive, simple task, but you’ll find that we can get into trouble rather quickly.  (You should run your project at this point to make sure that you actually navigate to your Page B file.) Add the same type of <Button> and event handler to PageB, but obviously point it at PageA this time.  Now, you have a button on each page that points to the other.  If you only use those buttons to do your navigation, you end up creating a HUGE back navigation stack, and it makes any concept of a Back button completely irrelevant. What we need to do in this case is to implement the GoHome event handler which is part of the LayoutAwarePage object that we’re using.  To effectively illustrate this example, add a second button to your PageB.xaml, with an accompanying new event handler. In this event handler, however, we’re not going to navigate to a page.  Instead, we’re going to create the GoHome event, and call that.  Here’s how that looks:

protected override void GoHome(object sender, RoutedEventArgs e)
{
    if (this.Frame != null)
    {
        while (this.Frame.CanGoBack) this.Frame.GoBack();
    }
}

 

private void HomeButton_Click(object sender, RoutedEventArgs e)
{
    base.GoHome(sender, e);
}

 

As you can see, our GoHome method runs a quick loop attempting to “GoBack” until it can’t anymore.  At that point, we end up back at the top of the navigation stack, on our initial page.  It’s a nice trick, but I think all of this is best illustrated with a quick video:

Passing Data Between XAML Pages in Windows 8

Next, we’re going to want to pass data between our pages.  Maybe an object, maybe a string, but data nonetheless.  As it turns out, our Frame.Navigate() method is overloaded to also accept a data parameter. For this sample, I’ve added a TextBox and a Button to my PageA, but at this point, I’m going to assume you know how to do that.  The important part of this is where I have an event handler that pulls the text value out of the TextBox and sends it as part of the Navigate() method.  Like this:

private void GoButton_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(PageB), TextBoxValue.Text);
}

 

 

On the other side, on PageB, we need to catch this data and display it.  Again, I’ve added a TextBlock in my sample code (which you can download at the end of this article), but the important piece is my new OnNavigatedTo event handler, and catching our data as it arrives.

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

 

    string text = e.Parameter as string;

 

    if (!string.IsNullOrWhiteSpace(text))
    {
        TextBlockValue.Text = text;
    }
    else
    {
        TextBlockValue.Text = "You need to pass a string. Press back and enter a value.";
    }
}

In PageB, we can grab the passed value from NavigationEventArgs.Parameter, where I am casting it as a string value.  You will need to cast your value to the appropriate type before you can use it, but once you have, you’ve tossed data from one page to the next!

In addition, I mentioned earlier that you can send complete objects using this mechanism as well.  Remember our Element class from way back in Day #4?  I’m going to pass a custom Element object from PageA to PageB in the next example.  Here’s PageA’s code:

private void Gallium_Click(object sender, RoutedEventArgs e)
{
    Frame.Navigate(typeof(PageB), new Element { AtomicNumber = 31,
                                                AtomicWeight = 69.72,
                                                Category = "Other Metals",
                                                Name = "Gallium",
                                                Symbol = "Ga",
                                                State = "Solid" });
}

You can clearly see that we’re passing a brand-new Element object to PageB.  Here’s PageB catching that data:

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

 

    Element gallium = e.Parameter as Element;
    TextBlockValue.Text = gallium.Category;
}

 

Caching Pages For Back Button Performance

The last thing we want to look at related to navigation is page caching.  For this final example, I am using our sample application in the state where I was passing string values back and forth.  You may have noticed, if you built your own sample app, that if you type something in the TextBox on PageA, and send that data to PageB, when you click the Back button to return to PageA, it doesn’t remember what you typed in the box.  This is an incredibly frustrating user experience pattern that you see on the web all the time.

We can avoid this with one simple line in the constuctor of the pages we want to cache:

public PageA()
{
    this.InitializeComponent();
    NavigationCacheMode = NavigationCacheMode.Enabled;
}

After you set the NavigationCacheMode, you will find that your TextBox values (and everything else on your page) will be cached in the back stack.  Give it a try…it’s a much better experience, and doesn’t require us to populate and repopulate the form every time the user returns to the page.

Summary

This was an extensive overview of navigation in XAML apps for Windows 8.  We covered moving between pages, passing data between pages, and caching those pages for when the user clicks the back button.

If you would like to download the complete code sample from this article, you can click the icon below.  (Please note that the Gallium button is currently disabled, you’ll need to uncomment the event handler for that button, as well as the code in PageB.xaml.cs to make that work.  PageB can only accept one type of parameter at a time, and it’s currently set up for the string.)

downloadXAML

Tomorrow, we’re going to start our conversation determining a user’s current location using GeoLocation, including the rules that go with using this technology.  See you then!

downloadTheTools

Tags

12 responses to “31 Days of Windows 8 | Day #13: Navigation”

  1. […] 31 Days of Windows 8 | Day #13: Navigation – Jeff Blankenburg continues his series of posts exploring the C# XAML implementation of navigation between pages / screens in Windows 8 Applications. Check out the article for a link to Clark Sell’s parallel article for HTML/JS applications. […]

  2. Philip Colmer Avatar
    Philip Colmer

    One problem with passing objects as parameters is that the Session Manager cannot cope with this. It raises an exception.

    Given that the Session Manager is provided as code that VS2012 adds to the project, it should – in theory – be possible to get the underlying objects to support exporting as XML and hopefully MS (or an enterprising dev) will add that in the future but, for now, if you want to use the Session Manager, you need to stick to the basic object types.

  3. […] on November 14, 2012 by Dan Rigby | Leave a reply Windows Store App Development31 Days of Windows 8 | Day #13: Navigation (Jeff Blankenburg)“In fact, in the first 12 days of this series, we’ve spent very […]

  4. […] Read original post by Jeff Blankenburg at BlankenBlog […]

  5. Brian Ouellette Avatar
    Brian Ouellette

    Your guys articles are the best! This navigation tutorial really helped me out! 🙂

  6. Kash Avatar
    Kash

    Hi,
    Thanks a lot for this article, but there is no sample to download. Is it normal ?

    1. jeffblankenburg Avatar
      jeffblankenburg

      My apologies. Somehow I forgot to link to the source code. It’s hosted on GitHub, and you can pull it from there.

      https://github.com/csell5/31DaysOfWindows8/tree/master/source/XAML/Day13-Navigation

  7. Umair Avatar
    Umair

    Sir i am facing a problem to my image.when i load it from folder it is reverted like mirror what’s the problem with it kindly give me solution…..

  8. Umair Avatar
    Umair

    Also define how to change the shape of button like your above post your back button is round shape.

  9. Ameer Hamza Avatar
    Ameer Hamza

    can you provide the tutorial for c++ as well ?

  10. Waseem Avatar
    Waseem

    Sir,i worked for me,,but a small problem happened,,,the back button of page b raises an exception…
    #if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
    UnhandledException += (sender, e) =>
    {
    if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break();
    };

    if i comment the //onnavigatedto event…..no exception is there,but as expected no value is passed…plz help me out

  11. Inayat Ali Jan Avatar

    Nice post…. To know more about navigation in Xaml visit this link:

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a website or blog at WordPress.com

%d bloggers like this: