When someone clicks the microphone icon in our app bar, we want to take them to a
new page where we can allow them to record a custom sound. To do this, we need to
create a second page in our app, and then navigate from the MainPage.xaml to that
new page. Navigation in Windows Phone Apps is similar to navigating from one web
page to another. In this lesson, we'll learn about the Navigation API and, even though
our needs are simple in this particular app, we'll find out the Navigation API capabilities
with regards to how the Windows Phone 8 operating system re-hydrates apps shut
down due to memory constraints.
Our game plan in this lesson ...
1. Revisit the Databound Project template to observe how it navigated from the main page to the details page.
2. Discuss the classes required for navigation in the Windows Phone 8 API.
3. Implement the code necessary to navigate from our main page to a new page that we'l use to record a custom sound.
1. Revisiting the Databound Project template to learn about navigation
If you'll recall a few lessons ago when we looked at the Databound Project Template,
we saw how tapping one of the list items ...
... navigates to another page containing more details about the given item:
In addition to the MainPage.xaml, the project template also has a second page called
DetailsPage.xaml:
In the MainPage.xaml.cs file, in the MainLongListSelector_SelectionChanged event
handler method, we see the code required to enable this. Focus on lines 47-50:
The NavigationService class is used to simply navigate from one XAML page to
another. However, it has a larger role in more complex scenarios. Since it is solely
responsible for navigation between XAML pages, it also allows you to inspect the
navigation history (called the "back stack"), remove entries from the back stack, and
then observe the effect that these changes have on the navigation through the app.
To learn about some of the advanced functionality of the NavigationService() class,
check out this article on MSDN:
However in our case, we merely need to navigate from the MainPage.xaml to a new
page. We don't need to worry about alternate back page scenarios, passing values
between the pages, or the like. Therefore, this other article on MSDN describes the
process we'll use in general terms, in case you want to do a little additional research:
Most of the simple navigation scenario is accomplished using the the Navigate() method in the code example.
Notice the Uri that is used as an input parameter to the Navigate() method. The Uri
object represents a Uniform Resource Indicator, similar to a URL but has more utility
and as more far reaching. The Uri has two basic parts—a string that represents a
location, and a UriKind that should be used to interpret the location string.
Let's start by parsing through the string ... you'll notice that it is part string literal, part
dynamic value that retrieves its value from the current selected item in the
LongListSelector. They are appended together with the plus + operator:
"/DetailsPage.xaml?selectedItem=" + MainLongListSelector.SelectedItem as
ItemViewModel).ID
The first part of the literal string should be obvious—it is the XAML page we want to
navigate to. Everything after that—i.e., after the question mark ? character—is a query
string. You've undoubtedly seen a query string before, even if you didn't know what it
was called. A query string is a means of sending additional information along with the
intended page to be loaded. I said you've undoubtedly seen this before because it is
one of two or three primary ways of sending additional data between stateless web
pages and is used ubiquitously on the World Wide Web.
If you look at a search for the name "Clint Rutkas" on Bing.com, the navigation bar in
your web browser will look like this:
It's simply a clever way of passing information from one web page that's intended to be
interpreted and processed by another web page.
In the code example we're examining, when someone taps an item in the
LongListSelector we want to send the ID for the item that was selected from the
MainPage.xaml to the DetailsPage.xaml ... the ? separates the page name from the
query string portion of the URL. The query string is in the form of a name / value pair.
For example:
selectedItem=3
... the selectedItem is the name of the pair, and everything after the equals character is
the value of the pair.
Two name / value pairs are separated by an & ampersand character. We'll see this
used later in this series to send geo-positional latitude and longitude from one page to
another ... it will look like this:
?latitude=41.8986&longitude= 87.6230
This is how you are able to pass multiple values in one string. Clever.
The second constructor argument for the new Uri takes an enumeration of type UriKind.
There are three possible values:
· UriKind.Relative
· UriKind.Absolute
· UriKind.RelativeOrAbsolute
In regards to the differences between the first two, check out this page:
... which says the following:
"Absolute URIs are characterized by a complete reference to the resource (example:
http://www.contoso.com/index.html), while a relative Uri depends on a previously
defined base URI (example: /index.html)."
In our case, a relative Uri would be "relative to the project's structure". When we prefix
the UriString with a forward-slash character / we're specifying the root of the project's
deployment package. That should correspond with what we see in the Solution Explorer
... the DetailsPage.xaml is in the root of the project folder. When the project is deployed,
those two .xaml files will both be in the root of the package like we saw when we
opened up the PetSounds.xap file as a zipped file.
But what about the UriKind.RelativeOrAbsolute? That's a bit trickier. The best I can
figure out is that we're simply asking the runtime to figure it out for itself. It will attempt to
clean up the UriString we provide and figure out where resources are. I think we could
switch that to UriKind.Relative and it would work, too.
Once the NavigationService loads the new page, the DetailsPage.xaml, an event called
OnNavigatedTo() fires. Notice its code:
In line 31, the NavigationContext.QueryString.TryGetValue("selectedItem") will retrieve
the value of the name / value pair in the query string as an out parameter if the
parameter name exists. Next, that selectedItem value is used to load the correct item
from the data model, and set it as the DataContext for the DetailsPage.xaml so that the
various TextBlock controls can bind to it (line 35).
Now that we have seen a full-fledged navigation example at work, we're better prepared
to tackle this in our own project.
2. Create the RecordAudio.xaml Page
Let's begin by creating that new page we want to navigate to:
1. Make sure you're in the C# file templates section
2. Select "Windows Phone Portrait Page"
3. Rename to: RecordAudio.xaml
4. Click the Add button
Back in the MainPage.xaml page, we'll revisit the event handler method stub we created several lessons ago called RecordAudioClick():
3. Implement the code to navigate to the new page
I'll replace the exception (intended to be a reminder) with the following line of code:
Hopefully, this version will be dramatically simplified when compared to the hairy
example we saw earlier. We create a new Uri object with a simple address to our new
RecordAudio.xaml page, and use the UriKind.RelativeOrAbsolute enum value.
Now, let's test that line of code by running the app and clicking the microphone icon in
the app bar:
... if all goes well, we should see a default page template like so:
Great! We'll need to revisit this notion later in this series of lessons with a slightly more
complex example in which we pass data between the pages.
Recap
To recap, the big take away from this lesson is how to navigate between XAML pages
using the NavigationService. We learned what a Uri object is, how to specify a page
location and even pass parameters between pages, what the UriKind enumeration
options mean, and so on.