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:
Example 1. Silverlight
Project: SilverlightShareData File: App.xaml.cs (excerpt)
public partial class App : Application { // public property for sharing data among pages public Color? SharedColor { set; get; }
. . .
} |
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. In those cases, the Background property is null and there shouldn’t be a Color stored in this
property. If the property were of type Color,
then a ColorColor
value would be transparent black, and that’s wrong. Even
non-transparent black is wrong if the user has selected the Light color
scheme. would be stored by
default; that
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:
Example 2. Silverlight
Project: SilverlightShareData File: MainPage.xaml.cs (excerpt)
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:
Example 3. Silverlight
Project: SilverlightShareData File: SecondPage.xaml.cs (excerpt)
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:
Example 4. Silverlight
Project: SilverlightShareData File: SecondPage.xaml.cs (excerpt)
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; }
|
The MainPage class
also overrides OnNavigatedTo so it too can retrieve the stored color and set
it to the background of the grid:
Example 5. Silverlight
Project: SilverlightShareData File: MainPage.xaml.cs (excerpt)
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); }
|
Now as you navigate
between the pages they always share the same color.
Using the App class as a repository for shared data among pages
is so convenient that you might find yourself using it exclusively. But
you should really consider more structured solutions that involve only
the pages navigating
between each other and not some third-party class like App.
Besides the OnNavigatedTo
virtual method, Page also defines an OnNavigatedFrom
method, which at first seems much less useful. After all, a page knows
that it’s navigating from itself because it’s just called Navigate or GoBack.
However, both OnNavigatedFrom
and OnNavigatedTo
have event arguments of type NavigationEventArgs,
which defines two properties: Uri of
type Uri, and Content
of type object.
These always indicate the page being navigated to.
For example, MainPage
calls Navigate with an argument of
“/SecondPage.xaml”. The OnNavigatedFrom
method in MainPage is called with
event arguments with a Uri property
indicating “/SecondPage.xaml” and a Content
property of type SecondPage. This is
the newly created instance of SecondPage that is about to be displayed, and this is the most
convenient way to obtain that instance. The OnNavigatedTo method of SecondPage is then called with the same event arguments
indicating a Uri of “/SecondPage.xaml”
and the SecondPage object.
Similarly, when SecondPage
calls GoBack, its OnNavigatedFrom
method is called with event arguments that include a Uri property indicating “/MainPage.xaml” and a
Content property with the MainPage instance. The OnNavigatedTo method of MainPage is then
called with those same event arguments.
This means that during the OnNavigatedFrom
method, a class has an opportunity to set a property or call a method in
the class of the destination page.
Let’s look at an example called SilverlightInsertData. The project has two pages
named MainPage and SecondPage and the XAML
files are the same as those you’ve already seen. The MainPage class doesn’t
have any logic to randomly change its color. Instead, it uses SecondPage to obtain a
color for it. You can think of SecondPage as a dialog box that returns a random color to
MainPage.
Here’s most of the code-behind
file in MainPage:
Example 6. Silverlight
Project: SilverlightInsertData File: MainPage.xaml.cs (excerpt)
public partial class MainPage : PhoneApplicationPage { public MainPage() { InitializeComponent(); }
public Color? ReturnedColor { set; get; }
void OnTextBlockManipulationStarted(object sender, ManipulationStartedEventArgs args) { this.NavigationService.Navigate(new Uri("/SecondPage.xaml", UriKind. Relative));
args.Complete(); args.Handled = true; } . . . }
|
Notice the ReturnedColor
property, of type nullable Color just like the property in the App class in
the previous program.
Here’s the SecondPage
code-behind file:
Example 7. Silverlight
Project: SilverlightInsertData File: SecondPage.xaml.cs (excerpt)
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); }
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; }
base.OnNavigatedFrom(e); } }
|
As in the previous programs, SecondPage changes its
background to a random color when touched, and calls GoBack when the TextBlock is touched. The new code is in the OnNavigatedFrom override, which is called
shortly after the class calls GoBack.
If there’s a valid SolidColorBrush available, the method checks if it’s navigating to
an object of type MainPage. If so, then
it saves the Color object in the ReturnedColor property of MainPage.
MainPage can retrieve the value of that property in its OnNavigatedTo override:
Example 8. Silverlight
Project: SilverlightInsertData File: MainPage.xaml.cs (excerpt)
public partial class MainPage : PhoneApplicationPage { . . . protected override void OnNavigatedTo(NavigationEventArgs args) { if (ReturnedColor != null) ContentPanel.Background = new SolidColorBrush(ReturnedColor.Value);
base.OnNavigatedTo(args); } } |
In a sense, MainPage
invokes SecondPage to obtain a Color value, just like a
real dialog box.
But if you navigate to SecondPage subsequent times, it always starts out with a
black screen (or white if you’ve selected the Light color theme).
Interestingly, SecondPage can’t initialize itself from any property
in MainPage because the OnNavigatedTo call that SecondPage receives
doesn’t reference the source page. To work in a symmetrical manner, SecondPage would need
to define its own public Color
property, and MainPage would need to initialize that property in its own OnNavigatedFrom override.
You might consider a
little variation on this program where SecondPage
defines the ReturnedColor property.
When MainPage navigates to SecondPage the OnNavigatedFrom
method in MainPage is called, and the method saves the instance of SecondPage being navigated
to in a field in MainPage. When SecondPage is finished, it saves the Color value in its ReturnedColor
property and calls GoBack. The OnNavigatedTo method in MainPage is then called. MainPage can use the SecondPage instance
saved as a field to access the ReturnedColor
property.
This scheme sounds fine, but
it won’t always work. The problem is that MainPage can’t be assured that the SecondPage instance it
navigates to will be the same SecondPage instance that navigates back to MainPage. You’ll have a
better sense of this problem soon.