This chapter is taken from book "Programming Windows Phone 7" by Charles Petzold published by Microsoft press. http://www.charlespetzold.com/phone/index.html
Page navigation would seem to be an advanced Silverlight programming topic, and a topic that applies only to Silverlight programming rather than XNA programming. However, there are issues involved with navigation that are related to the very important topic of tombstoning, which is what happens to your Windows Phone 7 application when the user navigates to another application through the phone's Start screen. Tombstoning is very much an issue that also affects XNA programmers.
Basic Navigation
The SilverlightSimpleNavigation project begins as usual with a
MainPage class, and as
usual I set the two TextBlock
elements for the titles and the content area of MainPage.xaml contains
only a TextBlock
that
sets a handler for its ManipulationStarted
event:
<StackPanel
x:Name="TitlePanel"
Grid.Row="0"
Margin="12,17,0,28">
<TextBlock
x:Name="ApplicationTitle"
Text="SIMPLE NAVIGATION"
Style="{StaticResource
PhoneTextNormalStyle}"/>
<TextBlock
x:Name="PageTitle"
Text="main page"
Margin="9,-7,0,0"
Style="{StaticResource
PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place
additional content here-->
<Grid
x:Name="ContentPanel"
Grid.Row="1"
Margin="12,0,12,0">
<TextBlock
Text="Navigate to 2nd
Page"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Padding="0 34"
ManipulationStarted="OnTextBlockManipulationStarted"
/>
</Grid>
Notice the Text
property on the TextBlock:
"Navigate to 2nd page." The code-behind file contains the handler for
ManipulationStarted but
also overrides the OnManipulationStarted
method for the whole page:
namespace
SilverlightSimpleNavigation
{
public partial
class MainPage
: PhoneApplicationPage
{
Random rand =
new Random();
public MainPage()
{
InitializeComponent();
}
void OnTextBlockManipulationStarted(object
sender, ManipulationStartedEventArgs args)
{
this.NavigationService.Navigate(new
Uri("/SecondPage.xaml",
UriKind.Relative));
args.Complete();
args.Handled = true;
}
protected
override void OnManipulationStarted(ManipulationStartedEventArgs
args)
{
ContentPanel.Background = new
SolidColorBrush(
Color.FromArgb(255, (byte)rand.Next(255),
(byte)rand.Next(255),
(byte)rand.Next(255)));
base.OnManipulationStarted(args);
}
}
}
If you touch anywhere on the page outside of the TextBlock, the background of the ContentPanel is set to a random color. Touch the TextBlock, and the handler accesses the NavigationService property of the page.
I created a second page in the SilverlightSimpleNavigation project by right-clicking the project name in the Visual Studio solution explorer, and selecting Add and New Item. From the Add New Item dialog box, I picked Windows Phone Portrait Page and gave it a name of SecondPage.xaml.
I gave the titles In SecondPage.xaml the same application name as
FirstPage.xaml but a page title of "second page" and the content area of
SecondPage.xaml is very much like MainPage.xaml but the
TextBlock reads "Go
Back to 1st Page":
<StackPanel
x:Name="TitlePanel"
Grid.Row="0"
Margin="12,17,0,28">
<TextBlock
x:Name="ApplicationTitle"
Text="SIMPLE NAVIGATION"
Style="{StaticResource
PhoneTextNormalStyle}"/>
<TextBlock
x:Name="PageTitle"
Text="second page"
Margin="9,-7,0,0"
Style="{StaticResource
PhoneTextTitle1Style}"/>
</StackPanel>
<!--ContentPanel - place additional content here-->
<Grid
x:Name="ContentPanel"
Grid.Row="1"
Margin="12,0,12,0">
<TextBlock
Text="Go Back to 1st Page"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Padding="0 34"
ManipulationStarted="OnTextBlockManipulationStarted"
/>
</Grid>
The code-behind file of the
SecondPage class is also very much like the
FirstPage class:
namespace
SilverlightSimpleNavigation
{
public partial
class SecondPage
: PhoneApplicationPage
{
Random rand =
new Random();
public SecondPage()
{
InitializeComponent();
}
void OnTextBlockManipulationStarted(object
sender, ManipulationStartedEventArgs args)
{
this.NavigationService.GoBack();
args.Complete();
args.Handled = true;
}
protected
override void OnManipulationStarted(ManipulationStartedEventArgs
args)
{
ContentPanel.Background = new
SolidColorBrush(
Color.FromArgb(255, (byte)rand.Next(255),
(byte)rand.Next(255),
(byte)rand.Next(255)));
base.OnManipulationStarted(args);
}
}
}
Let's run the program. The program begins with the main page, and you can touch the screen to change the color:

Now touch the TextBlock that says "Navigate to 2nd Page" and the second page comes into view:

You can touch that screen to change to a different color:

Now touch the TextBlock that says "Go Back to 1st Page". (Alternatively, you can press the phone's hardware Back button.) You'll be whisked back to the main page with the color just as you left it:

Passing Data to Pages
The possible use of pages as dialog boxes provokes two questions:
- How do I pass data from a source page to a destination page?
- How do I return data when going back to the original page?
The following project is called SilverlightPassData. It is very much
like the first project in this chapter except that when
MainPage
navigates to SecondPage,
it provides SecondPage
with its current background color, and
SecondPage
initializes itself with that color. Here's the content area of MainPage.xaml, the same as in the previous
program:
<Grid
x:Name="ContentPanel"
Grid.Row="1"
Margin="12,0,12,0">
<TextBlock
Text="Navigate to
2nd Page"
HorizontalAlignment="Center"
VerticalAlignment="Center"
padding="0 34"
ManipulationStarted="OnTextBlockManipulationStarted"
/>
</Grid>
I won't show you the
OnManipulationStarted
override because it's the same as in the previous program, but the
ManipulationStarted
event handler for the TextBlock
is a bit enhanced:
void OnTextBlockManipulationStarted(object
sender,
ManipulationStartedEventArgs args)
{
string
destination = "/SecondPage.xaml";
if
(ContentPanel.Background
is
SolidColorBrush)
{
Color clr = (ContentPanel.Background
as
SolidColorBrush).Color;
destination +=
String.Format("?Red={0}&Green={1}&Blue={2}",
clr.R, clr.G, clr.B);
}
this.NavigationService.Navigate(new
Uri(destination,
UriKind.Relative));
args.Complete();
args.Handled =
true;
}
The SilverlightPassData project also contains a
SecondPage class that
is the same as the one in the first project except that the code-behind file
contains an override of the OnNavigatedTo
method:
protected
override
void
OnNavigatedTo(NavigationEventArgs
args)
{
IDictionary<string,
string>
parameters = this.NavigationContext.QueryString;
if
(parameters.ContainsKey("Red"))
{
byte R =
Byte.Parse(parameters["Red"]);
byte G =
Byte.Parse(parameters["Green"]);
byte B =
Byte.Parse(parameters["Blue"]);
ContentPanel.Background =
new
SolidColorBrush(Color.FromArgb(255,
R, G, B));
}
base.OnNavigatedTo(args);
}
Now as you navigate from MainPage to SecondPage, the background color remains the same. As you go back, however, that's not the case. There is no built-in facility like the query string to return data from one page to another.
Sharing Data Among Pages
Keep in mind that all the pages in your program have convenient access to the App class that derives from Application. The static Application.Current property returns the Application object associated with the program, and you can simply cast that to App. This means that you can use the App class for storing data you want to share among multiple pages of the application.
In the SilverlightShareData project, I defined a simple public property in the App class, I defined this property of type nullable Color rather than just Color for those cases where a SolidColorBrush has not been set on the Background property of ContentPanel.
public
partial
class
App
: Application
{
//
public property for sharing data among pages
public
Color?
SharedColor { set;
get;
}
....
}
Much of the program remains the same, except that when you touch the TextBlock in MainPage, the handler first attempts to save a color in the new App class property before navigating to SecondPage:
void OnTextBlockManipulationStarted(object
sender,
ManipulationStartedEventArgs args)
{
if
(ContentPanel.Background is
SolidColorBrush)
(Application.Current
as
App).SharedColor
=
(ContentPanel.Background as
SolidColorBrush).Color;
this.NavigationService.Navigate(new
Uri("/SecondPage.xaml",
UriKind.Relative));
args.Complete();
args.Handled =
true;
}
The OnNavigatedTo override in SecondPage than accesses that
property:
protected
override
void
OnNavigatedTo(NavigationEventArgs
args)
{
Color?
sharedColor = (Application.Current
as
App).SharedColor;
if
(sharedColor != null)
ContentPanel.Background =
new
SolidColorBrush(sharedColor.Value);
base.OnNavigatedTo(args);
}
Similarly, when you press the TextBlock on SecondPage, the handler saves whatever color the background now happens to be back in the App class before calling GoBack:
void OnTextBlockManipulationStarted(object
sender,
ManipulationStartedEventArgs args)
{
if
(ContentPanel.Background is
SolidColorBrush)
(Application.Current
as
App).SharedColor
=
(ContentPanel.Background as
SolidColorBrush).Color;
this.NavigationService.GoBack();
args.Complete();
args.Handled =
true;
}
Retaining Data across Instances
If we want SecondPage to "remember" the last color it was set to, something outside of SecondPage must be responsible for saving that data. That could be MainPage. Or, SecondPage could save its state in isolated storage. Isolated storage is much like regular disk storage. To access it, you use classes in the System.IO.IsolatedStorage namespace. Every Windows Phone 7 application has access to isolated storage but only to files that the application itself has created. Isolated storage allows an application to save data between multiple executions, and is ideal for saving application settings.
Let's modify the previous program so that
SecondPage uses this State property. In the
SilverlightRetainData project, everything is the same except for a using
directive for the Microsoft.Phone.Shell namespace and two overrides in
SecondPage. Here they are:
protected
override
void
OnNavigatedFrom(NavigationEventArgs
args)
{
if
(ContentPanel.Background is
SolidColorBrush)
{
Color clr = (ContentPanel.Background
as
SolidColorBrush).Color;
if (args.Content
is
MainPage)
(args.Content
as
MainPage).ReturnedColor
= clr;
// Save color
PhoneApplicationService.Current.State["Color"]
= clr;
}
base.OnNavigatedFrom(args);
}
protected
override
void
OnNavigatedTo(NavigationEventArgs
args)
{
//
Retrieve color
if
(PhoneApplicationService.Current.State.ContainsKey("Color"))
{
Color clr = (Color)PhoneApplicationService.Current.State["Color"];
ContentPanel.Background =
new
SolidColorBrush(clr);
}
base.OnNavigatedTo(args);
}
Now go back to MainPage. The color you set in SecondPage is displayed. From MainPage, press the phone's hardware Start button, leaving the program. Navigate around a bit if you want but eventually start pressing the Back button to come back to SilverlightRetainData and MainPage.
Summary
I hope this article helps you to learn Page Navigation and Passing, Sharing and Retaining Data in Windows Phone 7.

Join the conversation! Your thoughts help the community grow.