(X) Hide this
    • Login
    • Join
      • Say No Bots Generate New Image
        By clicking 'Register' you accept the terms of use .

Windows Phone 7 - Part #3: Understanding navigation

(9 votes)
Andrea Boschin
>
Andrea Boschin
Joined Nov 17, 2009
Articles:   91
Comments:   9
More Articles
9 comments   /   posted on Feb 02, 2011
Categories:   Windows Phone

This article is compatible with the latest version of Silverlight for Windows Phone 7.

Coming from the previous part, the second, where I discussed multiple aspects of the page in Windows Phone and the "Metro" theme, now it is time to make another step on our path. Just in the first article of the series, when I was introducing the differences between Silverlight for desktop and for the phone, I said that differently from the desktop version when you write for your device the applications are always navigation apps. This simply sentence means you have always to deal with a paradigm that makes your software more like a web application instead of a traditional application made of multiple Forms and modal and non-modal popups. So, let me introduce the paradigm and then speak about the tools you can use in your Windows Phone 7.

This is the planned Table of Contents for the whole series. If you recommend adding another topic to the TOC - please feel free to comment below the article.

Windows Phone 7 Part #1: Getting Started 
Windows Phone 7 Part #2: Your first app
Windows Phone 7 Part #3: Understanding navigation 
Windows Phone 7 Part #4: The application lifecycle
Windows Phone 7 Part #5: Panorama and Pivot controls 
Windows Phone 7 Part #6: Advanced interaction
Windows Phone 7 Part #7: Understanding Push Notifications
Windows Phone 7 Part #8: Using Sensors

The navigation paradigm

The concept of navigating between pages is obviously strictly related to the web paradigm. When you write for the web, you have to deal directly with the fact that you are running in a browser. You can elaborate only a page at a time then send it to the browser and every page you create is completely separated from the other pages, also if it needs to share some informations with them. The problem with this paradigm is that as it augments the power of the user, that can easily switch from different pages using navigation buttons, it strongly increases the difficulties for the programmer that have to deal with the multiple combinations of pages a user can visit.

But from the user point of view the navigation applications are much more user-friendly than the traditional paradigm. Every page has a single and specific function and he can simply jump back if  he needs to correct something wrong without being restricted by an unnatural flow. As you soon learn, also from a programmer point of view, writing navigation applications is not so hard; after understanding how to deal with navigation issues, you understand the every single page is a little part of the application, almost isolated from the others and this make the programming simpler.

The navigation paradigm heavily permeates your phone. One of the three allowed hardware buttons is the back button that occupies the leftmost position. So, once you start approaching the phone programming you have for sure to embrace this model, in the good and in the bad things.

Exploring the toolset

In Silverlight for desktop, when you write navigable apps, you have to use a special set of controls, expecially the Page and the Frame. In Windows Phone there is two counterparts to these controls, named PhoneApplicationPage and PhoneApplicationFrame. Since the frame is the container for the pages you may figure out that you have to put it somewhere and then point it to the pages, but if you remember my first issue in this series, the PhoneApplicationFrame is initialized inside of the App.xaml.cs during the application startup. It is created and set to the RootVisual ,then depending to what it is defined in the default task into the WMAppManifest.xaml, the runtime injects the initial page and the program starts. So, you will have always a single PhoneApplicationFrame and multiple PhoneApplicationPages. As far as I experimented there is not any other option.

Once you have created your pages you can use the NavigationService to trigger the navigation from a page to another. NavigationService is exposed bya a a property of the PhoneApplicationPage class and it has some methods you can use to control the navigation. As you can see in MSDN documentation the methods are self-explanatory; you can Navigate(), GoForward(), GoBack() and with the properties you can control if navigation is enabled for both the directions with CanGoBack and CanGoForward.

this.NavigationService.Navigate(new Uri("/ProductPage.xaml", UriKind.Relative));

There is two important things you have to keep in mind when you need to trigger a navigation: First of all, navigation caching is not under your control. Differently from Silverlight from desktop you do not have a NavigationCacheMode property. The runtime always apply a given policy to page caching that use the following flow:

  1. When you forward-navigate to a page it creates always a new instance.
  2. When a page is put in the backstack it is cached
  3. When a page is pulled out of the backstack it is removed also from cache

The second important thing, to have in mind, is the backstack policy. Remember that when you call the Navigate method the page you are leaving is always pushed to the backstack. Given that you have to navigate from A to B then to C and then you navigate again from C to B it is not always true you want C in the backstack. If C is simply a configuration page there is not any reason because it remain into the backstack. To work around to this problem you can use instead the GoBack method that differently from Navigate does not affect the backstack. So in our case, when you go back from C to B, C is simply destroyed and it never enters the backstack. I know this may be difficult to understand without an example so I've created a small video to illustrate the behavior.

See the video

Navigation events

Handling correctly the navigation does not involve only to deal with the backstack. One important thing to know is when someone enters or exit to or from your page. There are a bunch of reasons for this: you may need to inizialize the page, reload its content, of simply apply a transition between the new page and the previous or the following. For these cases the PhoneApplicationPage exposes a series of overridables methods that will notify you when something happen to the navigation.

  • OnNavigatedTo : raised when the user enters the page
  • OnNavigatingFrom : raised just before the user leave the page, let you stop the navigation with the Cancel property
  • OnNavigatedFrom : raised after the user leaved the page
  • OnBackKeyPress : let you know when the user press the back button. You can also cancel the navigation.

The methods are easy to understand, so I think there is not the need of giving a deep explanation of each one. I only want to speak about the OnBackKeyPress event that gives us a little more control over the user navigation. This event is raised only when the user press the back button and not when you call the GoBack method on NavigationService. The good thing is that you can always stop the navigation using the Cancel property in the CancelEventArgs you receive from the caller. This is really useful particularly in pages when you need to ask the user if you have to save the information he have entered. Nothing prevent you from popping out a message box to ask a confirmation of the user action. Many of the Windows Phone devices (almost all) have capacitive buttons as hardware buttons and it is not unusual the back navigation is unwanted. So it is a good thing to ask a confirmation when there are sensitive data to preserve.

An interesting case when you need to handle navigation events is when you have to perform some transitional animations between pages. The switch from a page to another is usually very fast, so if you correctly forge enter and exit animations it is easy to give your user a beautiful feedback. Given that you created an "enter" and an "exit" animation that animate the UI content from the empty page to the complete interface and viceversa,  the following overrides let you perform the transitions correctly.

public partial class DietHistoryPage : PhoneApplicationPage
{
    public DietHistoryPage()
    {
        InitializeComponent();
    }
 
    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    {
        enter.Stop();
        enter.Begin();
        base.OnNavigatedTo(e);
    }
 
    protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
    {
        enter.Stop();
        enter.Begin(
            () => base.OnNavigatingFrom(e));
    }
 
    protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)
    {
        exit.Stop();
        exit.Begin(
            () => base.OnBackKeyPress(e));
    }
}
 
public static class Animations
{
    public static void Begin(this Storyboard sb, Action completionCallback)
    {
        EventHandler handler = null;
 
        handler = (a, b) =>
        {
            completionCallback();
            sb.Completed -= handler;
        };
 
        sb.Completed += handler;
        sb.Begin();
    }
}

The code is taken from my Diet Assistant application you can download and try from the marketplace. It uses lots of beautiful animations when switching from a page to another. The trick is made using lambda expressions. Thanks to them it is easy to retain the event args sent to the navigation methods, perform the animation and then call the base class when the animation is completed to continue the navigation. The Begin extension method in the Animations class correctly handles the Completed event to attach and detach the handler to avoid memory leaks.

When you submit your application to the marketplace, the bad handling of the back button is one of the first issues that causes a failure in the certification. One case you have to keep in mind is the rule of the certification that wants the back-button closes a popup. In these cases, the back button have to be handled to stop the navigation to the previous page and instead it have to close the popup. To achieve this result you have simply to intercept the back button with the OnBackKeyPress event, close the popup and then set the Cancel property to false. This prevent the runtime to go back in the stack but leaves the current page still available. Obviously if the popup is not open you have to continue the back navigation as usual.

Preserve the state across pages

Using the navigation paradigm opens the way to a problem that usually it is common in web applications. When you have to pass informations between pages in a web application you have some options that usually involve the use of cookies, session, querystring and so on. The problem is given by he fact that every page is virtually isolated from every other page, and even if they have to share something, they do not exist at the same time so there is the need of some tricks to enable this sharing.

When you deal with navigation in Windows Phone, it may sounds strange, but you have the same scenario to manage and the solutions to this problem is a least the same as a web application. First of all, when you call a page using the NavigationService you can easily add some information for the target page using a QueryString:

private void Button_Click(object sender, RoutedEventArgs e)
{
    this.NavigationService.Navigate(
        new Uri("/ProductPage.xaml?SKU=12345670", UriKind.Relative));
}

Then when you are in the new page you can use the NavigationContext property to read the informations you have previously sent. The NavigationContext exposes a QueryString property that lets you access the various parameters passed with the common url syntax.

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    this.SKU = this.NavigationContext.QueryString["SKU"];
    base.OnNavigatedTo(e);
}

If you want you can be more elegant and apply a mapping to the URIs you have to call. First of all add to the App.xaml the following code:

<Application.Resources>
    <nav:UriMapper x:Key="UriMapper">
        <nav:UriMapping MappedUri="/ProductPage.xaml?SKU={SKU}" Uri="/Product/{SKU}" />
    </nav:UriMapper>
</Application.Resources>

Then you have to assign the UriMapper you created in the resources with the PhoneApplicationFrame. In the inizialization phase you have to adde this simple code, just after the call to InizializePhoneApplication in App.xaml.cs:

this.RootFrame.UriMapper = this.Resources["UriMapper"] as UriMapper;

This means you can use a beautified url in place of the raw one. I don't know if this is very useful since url mapping is usually a problem for web applications related to search engine optimization but, I figure out, someone can find a reason to do this:

private void Button_Click(object sender, RoutedEventArgs e)
{
    this.NavigationService.Navigate(
        new Uri("/Product/12345670", UriKind.Relative));
}

Unfortunately the query string is not useful when you need to pass complex objects from a page to another. Let say you have to send to the incoming page the entire Product instance to avoid the access to the network to read agai it from a WCF service. In this case the PhoneApplicationService, that is instantiated into the App.xaml exposes a State property that is a dictionary you can use to persist informations. Here is an example:

// in the calling page
PhoneApplicationService.Current.State["Product"] = DataService.GetProductById("12345670");
// in the destination page
Product theProduct = PhoneApplicationService.Current.State["Product"] as Product;

Final thoughts

As we have seen, the navigation paradigm is supported by a good set of tools in Silverlight for the Windows Phone 7. We have a fine control on the events raised on the page during the navigation and we can control how to navigate to other pages, also using friendly-urls and maintain the state across different pages. At the first sight it may seems difficulty to handle correctly the navigation but after a little training you will agree that this is the sole model that may fully satisfy the user while using its phone and that also your applications are easy to develop. The next step in our path will be the knowledge of the so-called "application lifecycle".

About the Author

Andrea BoschinAndrea Boschin is 41 years old from Italy and currently lives and works in Treviso, a beautiful town near Venice. He started to work in the IT relatively late after doing some various jobs like graphic designer and school teacher. Finally he started to work into the web and learned by himself to program in VB and ASP and later in C# and ASP.NET. Since the start of his work, Andrea found he likes to learn new technologies and take them into the real world. This happened with ASP.NET, the source of his first two MVP awards, and recently with Silverlight, that he started to use from the v1.0 in some real projects.
 


Subscribe

Comments

  • ppopadiyn

    RE: Windows Phone 7 - Part #3: Understanding navigation


    posted by ppopadiyn on Mar 29, 2011 22:01

    Hi,

    Do you know if the Panorama and Pivot pages could be used in navigation scenario. For example: I have a main page and I wanna navigate to a second page. When that second page contains Panorama (or Pivot) controls, it always throws an exception. But if I use a normal page everything works perfect. I am unable to find any useful information over the web. All tutorials I've seen demonstrate the Panorama as a home screen of the application and it will be quite strange if it is not possible to use it as a second page (for example).

    10x

  • ppopadiyn

    RE: Windows Phone 7 - Part #3: Understanding navigation


    posted by ppopadiyn on Mar 29, 2011 22:15
    Ha I found the problem, my Panorama page was in a separate assembly, and there wasn't a reference to the Microsoft.Phone.Controls assembly in the main assembly. No it works ;)
  • -_-

    RE: Windows Phone 7 - Part #3: Understanding navigation


    posted by Usman ur Rehman Ahmed on May 09, 2011 03:19
    Thanks for clarifying points about BackStack policy however when you say "forward-navigate", do you refer to "Navigate()" or "GoForward()" method or both?
  • -_-

    RE: Windows Phone 7 - Part #3: Understanding navigation


    posted by Andrea Boschin on May 09, 2011 09:51
    with forward-navigation here I mean the Navigate method. Thanks
  • tianyutingxy

    Re: Windows Phone 7 - Part #3: Understanding navigation


    posted by tianyutingxy on Nov 28, 2011 13:49

    I got a problem,I build two pages,One is MainPage I put a button on this page,and set it's click event logic as  navigate to a new page which named page1,the in the page1 i define a method like this ~page1(){}.then i start my test,in MainPage i click the button just define,and navigated to page1 as result.then in page1 i press backkey,GoBack to MainPage but the breakpoint i set at ~page1(),was not triggerd,i dont konw why can you explan it? thanks.

  • BennyNeugebauer

    Re: Windows Phone 7 - Part #3: Understanding navigation


    posted by BennyNeugebauer on Jun 17, 2012 18:18
    Thank you very much for this article!  The PhoneApplicationService.Current.State I did not know yet. :-)
  • KoldoKoldoKoldo

    Re: Windows Phone 7 - Part #3: Understanding navigation


    posted by KoldoKoldoKoldo on Jun 23, 2012 10:03
    Hello Andrea,

    I have been for a few days looking for information about this subject and I could not find anything.

    let me explain:

    I have an application that uses live tiles,
    what I do normally is in the view (PhoneApplicationPage) pointed from live tile application in it´s method OnNavigatedTo, I ask for the parameters I need to know about the live tile parameters:


    for example:
    if (NavigationContext.QueryString.TryGetValue ("panoramaItem" panoramaItem out))
                 {
                     panoramaItem = "0";
                 }



    So far so good, but I need to do this same check in the App.xaml.cs. Application_Launching

    can it be done in App.xaml.cs?, Or can I know parameters that have started the application?

    Thank you very much for your help!

     

  • KoldoKoldoKoldo

    Re: Windows Phone 7 - Part #3: Understanding navigation


    posted by KoldoKoldoKoldo on Jun 26, 2012 17:28
    Hurra, I found it!

    At the end of the App constructor we add an event handler to the Navigating event

    RootFrame.Navigating + = new NavigatingCancelEventHandler (RootFrame_Navigating);

    and every time we started, we finalize or change view or page pass through this event,

    the event is:

    private void RootFrame_Navigating (object sender, NavigatingCancelEventArgs e)
     {
         / / e.Uri has the complete application uri
         / / MessageBox.Show (e.Uri.ToString ());
     }

    I've discovered thanks to these two urls:

      http://social.msdn.microsoft.com/Forums/en-US/windowsphone7series/thread/4a9d6c9d-1c73-48ae-ac04-29912b5ceadc
      http://blogs.msdn.com/b/ptorr/archive/2010/08/28/redirecting-an-initial-navigation.aspx

    Thanks to Peter Torr and rhizohm.

    Authentic cracks!

    ------------------------------------------

    let me do a little auto promo,
    if you have websites or applications and would like to know what your users are doing, this app is for you!!.

    analytics client

    windowsphoning

  • venkatasuresh

    Re: Windows Phone 7 - Part #3: Understanding navigation


    posted by venkatasuresh on Aug 24, 2012 16:04

    Sir,

    When Root System Navigation failed will occur?

Add Comment

Login to comment:
  *      *       

From this series