March 2011

Volume 26 Number 03

Mobile Matters - Windows Phone Navigation: The Basics

By Yochay Kiriaty | March 2011

Silverlight Windows Phone applications have a Web-like page model where the end users navigate from one page to another. There’s a dedicated hardware Back button to easily navigate back to previous pages (without consuming screen real estate), and the journaling (or history) of your navigation is integrated with the platform to ease navigating or transitioning across different applications. This two-part article will:

  • Introduce you to the page navigation model on Windows Phone.
  • Provide the best practices you’ll need to get the most out of the current APIs–such as integration with the hardware Back button, optimized loading and unloading of pages, and ensuring your navigation model meets Windows Phone certification guidelines.
  • Introduce actionable, easy-to-follow recipes to create the most complex navigations not implemented with the current APIs, including transient content and page transitions.

Windows Phone Nav Model

The Windows Phone navigation model consists of a frame (PhoneApplicationFrame) and one or more pages (PhoneApplicationPage) that hold the content loaded into the frame.

The PhoneApplicationFrame exposes most of the navigation events and exposes the Navigate method you’ll use to go across pages. It also determines the client area for the application and reserves the space for the application bar and the system tray. 

PhoneApplicationPage has page-specific notifications for when a page is navigated to and when a user navigates away from a page. It also handles the events related to the hardware Back button.

Both PhoneApplicationFrame and PhoneApplicationPage share a NavigationService; this service is actually doing the navigation. Windows Phone supports journaling (tracking the history of the pages you’ve loaded so you can go back to a previous page) and exposes APIs so you can go back. Forward navigation isn’t supported on the phone.

Windows Phone has three dedicated hardware buttons: Back, Start and Search. There are specific application-certification requirements around handling of the hardware Back button:

  • An application shouldn’t prevent the user from going back to a previous page. The only possible exception is a prompt when data loss is involved–you can then prompt to confirm and let the user through if he chooses to navigate back.
  • If a popup, the Software Input Panel (SIP) or other transient dialog is open, pressing the hardware Back button should dismiss this dialog but not leave the current page (effectively canceling the Back button navigation).
  • Pressing the Back button while in the first screen of an application must exit the application. This functionality comes for free. If you don’t prevent the navigation, the framework exits for you—in fact, this is the only way to exit a Silverlight application. There’s no Exit method in the exposed APIs.
  • To maintain a consistent user experience (UX) across apps, the Back button should only be used for backward navigation.

In addition to the Back button’s critical role in navigation, the Start button also participates in navigation. When the user presses the Start button, the running application is deactivated and a context switch is performed as you navigate forward to the Start menu. From here a user can launch another application and navigate within the new application, or he can choose to navigate back (using the hardware Back button) to the previously running application. This effectively creates a navigation model where the Back button navigates through the pages of a running application or through the stack of previously running application.

Windows Phone APIs

As noted earlier, the core players for navigation are PhoneApplicationFrame and PhoneApplicationPage.

PhoneApplicationFrame acts as the RootVisual for the application. At startup, a PhoneApplicationFrame is instantiated in the App class in App.xaml.cs (see Figure 1).

Figure 1 Instantiation of RootFrame in App.xaml.cs

private void InitializePhoneApplication()
{
  if (phoneApplicationInitialized)
        return;
  // Create the frame but don't set it as RootVisual yet; this allows the splash
  // screen to remain active until the application is ready to render.
  RootFrame = new PhoneApplicationFrame();
  RootFrame.Navigated += CompleteInitializePhoneApplication;
           
  // Handle navigation failures
  RootFrame.NavigationFailed += RootFrame_NavigationFailed;
  // Ensure we don't initialize again
  phoneApplicationInitialized = true;
}

The runtime automatically navigates to the instance of PhoneApplicationPage, which is specified by the NavigationPage attribute in the DefaultTask on the WMAppManifest.xml application manifest, as shown here:

<Tasks>
  <DefaultTask  Name ="_default" NavigationPage="MainPage.xaml"/> 
</Tasks>

Getting a bit closer to responsibilities and APIs, PhoneApplicationFrame exposes most of the navigation methods and events we’ll need for this article. Figure 2 lists the most relevant methods, properties and events in PhoneApplicationFrame.

Figure 2 PhoneApplicationFrame Methods, Properties and Events

Name Type Description
Navigate Method Navigates to a new PhoneApplicationPage specified by the URI parameter. The parameter is a Uri, so a Navigate call effectively instantiates the new page and navigates to it (you don’t pass it an already instantiated page).
CanGoBack Read-Only Property Returns true if the application’s back stack (the journaling history) isn’t empty. This means users have navigated forward at least once within the app. If the application is in the first page loaded in the app, CanGoBack will return false and you won’t be able to programmatically call GoBack, but the end user can still press the hardware Back button and the application will exit because it’s going back to the previously running application.
CanGoForward Read-Only Property Not applicable to Windows Phone. It’s always false because forward navigation isn’t supported.
UriMapper Property Gets/Sets a UriMapper. Beyond our scope for this article, but worth mentioning that Uri mapping is supported.
GoBack Method Navigates to the most recent entry in the back stack. This method will throw an exception if there’s no entry in the back stack; always check CanGoForward before calling this method.
GoForward Method Not supported on Windows Phone; will throw InvalidOperationException
Navigating Event Occurs when a new navigation is requested. At this point, it can still be canceled by setting the Cancel property in the NavigatingCancelEventArgs parameter to true. Please see notes later on about why you shouldn’t cancel back navigations in this event.
Navigated Event Occurs when a navigation has been executed. This doesn’t mean that the page content that was navigated to has been loaded. It simply occurs when the content has been found and navigated to.
NavigationFailed Event Occurs when an error has been encountered.
NavigationStopped Event Occurs when navigation is stopped by either calling the StopLoading method or more commonly when a new navigation is requested and a navigation was in progress.

Most are inherited from Frame, so for those familiar with the Silverlight Frame class, these methods should look familiar. The list in Figure 2 isn’t inclusive of all PhoneApplicationFrame features, just the relevant ones for navigation.

Code Walk-Through: To see all these events and properties in action, explore AllNavigationsEvents.xaml.cs in the sample code accompanying this article. You can also see the order in which events fire in Figure 3.

image: ng>The Sequence of Events as You Navigate Across Pages

Figure 3 The Sequence of Events as You Navigate Across Pages

PhoneApplicationFrame also determines the client area that the application will get and reserves the space for the application bar and the system tray. This detail will be relevant as we navigate across pages that have an application bar because it’s specified at the page level, and there’s a system-wide animation to show and hide the application bar as a page gets loaded.

The second participant in the navigation is PhoneApplicationPage. It plays two critical roles in navigation:

  • Handling of the hardware Back button presses.
  • Providing events for page lifecycle to know when a page is activated/deactivated.

For integration with the hardware Back button, PhoneApplicationPage exposes a BackKeyPress event. The page also has a virtual OnBackKeyPress method you can override in your instance of a page to handle and even cancel a Back button press event.

PhoneApplicationFrame has a Navigating event and an OnNavigatingFrom notification/callback. Within both of these, you can cancel navigations to other pages within the app by setting e.Cancel = true in the NavigationCancelEventArgs parameter passed to these methods; due to a known bug on the platform, you shouldn’t cancel Back button navigations from these events/methods. If you do cancel a hardware Back button press in this event, your navigation will break and the application will need to be restarted. The only two recommended methods for canceling a hardware Back button press are the PhoneApplicationPage BackKeyPress event and the OnBackKeyPress callback.

See Figure 4 for a list of events and methods where navigations can be canceled, with recommendations on whether a Back press can be canceled in that method, and advice on how to check if the event was a back navigation.

Figure 4 Events and Methods Where Navigations Can Be Canceled

Owner Event/Notification Can Cancel a  New Navigation Can Cancel Back Navigations Check for Back Navigations
PhoneApplicationFrame Navigating Yes No Yes; check e.NavigationMode != NavigationMode.Back
PhoneApplicationPage OnNavigatingFrom Yes No Yes; check e.NavigationMode != NavigationMode.Back
PhoneApplicationPage OnBackKeyPress No (called only when Back key press is called) Yes Not needed; only called on hardware Back key press
PhoneApplicationPage BackKeyPress (event) No (called only when Back key press is called) Yes Not needed; only called on hardware Back key press

PhoneApplicationPage complements these events to complete the navigation lifecycle with the more useful OnNavigatedTo and OnNavigatedFrom method callbacks for the page. To better understand and easily remember when these callbacks are called, it’s best to complete their method names with a “this page.” One method is called when the user has “navigated to this page,” and later the other method gets called when the user is “navigated from this page” onto another page.

Figure 3 shows the sequence of events as you navigate across pages. The symmetry between NavigatedTo/NavigatedFrom makes these two methods ideal for starting and stopping work that’s required when the page is visible, but not required when the page is in the back stack. Also notice that NavigatedTo always fires before a page is loaded, so don’t assume the contents of the page are loaded at this time.

The reason OnNavigatedTo and OnNavigatedFrom are critical to Windows Phone is because of the back stack. The OS maintains the back stack for pages you can go back to, so pages aren’t immediately unloaded, destroyed or garbage collected when a navigation happens from one page to another. Instead, the pages are moved to the back stack and kept alive (in memory), and when the user clicks back to get to that page, the page is simply added back into the visual tree. The page isn’t recreated (unless the application has been deactivated and tombstoned between when the user left the page and clicked back). Because forward journaling isn’t supported, pages are eligible for garbage collection when you navigate from a page back to the previous page—assuming there are no other references to this page.

Figure 5 shows a diagram that illustrates a PhoneApplicationPage lifecycle.

image: The PhoneApplicationPage Lifecycle

Figure 5 The PhoneApplicationPage Lifecycle

As you navigate from Page1 to Page2 and then Page3, pages aren’t garbage collected until you call the GoBack method from the page. Inactive pages are in the back stack, but still in memory. If these pages are listening to global events, the event listeners are still active.

Despite a page not getting garbage collected when you navigate from it, the page is no longer visible or active until you navigate back to it, so you should make sure you do any cleanup and release any expensive resources when the user has navigated away from a page. For example, if you’re listening to location changes using GeoCoordinateWatcher, you should stop the listener on the OnNavigatedFrom and restart it when the user navigates back to your page–and your page OnNavigatedTo is called.

Code Walk-Through: To see how pages are retained in memory while they’re in the back stack, explore the GarbageCollectedSample page included in the accompanying code download. It keeps a running tally of pages in memory, and you can see it increase as you navigate forward and decrease as you navigate back from a page.

That wraps up the first part of our series. Next month, we’ll focus on advanced navigation topics.


Yochay Kiriaty is a senior technical evangelist at Microsoft, focusing on client technologies such as Windows and Windows Phone. He coauthored the books “Introducing Windows 7 for Developers” (Microsoft Press, 2009) and “Learning Windows Phone Programming” (O’Reilly Media, 2011).

Jaime Rodriguez is a principal evangelist at Microsoft driving adoption of emerging client technologies such as Silverlight and Windows Phone. You can reach him on Twitter: @jaimerodriguez or on blogs.msdn.com/jaimer.

Thanks to the following technical expert for reviewing this article: Peter Torr