Every program installed on
Windows Phone 7 has access to its own area of permanent disk storage
referred to as isolated storage, which the program can access using classes in
the System.IO.IsolatedStorage namespace. Whole files can be read and written to in
isolated storage. For the program that following I’m going to
focus instead on a special use of isolated storage for storing application settings. The IsolatedStorageSettings
class exists specifically for this purpose.
For
application settings, you should be thinking in terms of the whole
application rather than a particular page. Perhaps some of the application settings
apply to multiple pages. Hence, a good place to deal with these
application settings is in the program’s App
class.
Not coincidently, it is the
App.xaml file that creates a PhoneApplicationService
object (the same PhoneApplicationService
object used for saving
transient data) and assigns event handlers for four events:
<shell:PhoneApplicationService Launching="Application_Launching"
Closing="Application_Closing"
Activated="Application_Activated"
Deactivated="Application_Deactivated"/>
The Launching event is fired when the program is first
executed from the Start screen. The Deactivated event occurs when the program is tombstoned, and the Activated event
occurs when the program is resurrected from tombstoning. The Closing event
occurs when the program is really terminated, probably by the user
pressing the Back button.
So, when a program starts up,
it gets either a Launching event or an
Activated
event (but never both), depending whether it’s being started from the
Start screen or coming out of a tombstoned state. When a program ends,
it gets either a Deactivated event or a
Closing
event, depending whether it’s being tombstoned or terminated for real.
A program should load application settings during the
Launching event and save them in
response to the Closing event. That much is obvious. But a program should also
save application settings during the Deactivated event because the program really doesn’t know if it
will ever be resurrected. And if it is resurrected, it should load application settings during
the Activated
event because otherwise it won’t know about those settings.
Conclusion: application settings should be loaded
during the Launching and Activated events and saved during the Deactivated and Closing
events.
For the SilverlightIsolatedStorage program, I decided that the
number of taps should continue to be treated as transient data—part of
the state of the page. But the background color should be an application
setting and shared among all instances.
In App.xaml.cs I defined the
following public property:
Example 1. Silverlight
Project: SilverlightIsolatedStorage File: App.xaml.cs (excerpt)
public partial class App : Application { // Application settings public Brush BackgroundBrush { set; get; } . . . }
|
Conceivably this can be one of
many application settings that are accessible throughout the
application.
App.xaml.cs already has empty event handlers for all
the PhoneApplicationService events. I gave each handler a body consisting of a single
method call:
Example 2. Silverlight
Project: SilverlightIsolatedStorage File: App.xaml.cs (excerpt)
private void Application_Launching(object sender, LaunchingEventArgs e) { LoadSettings(); }
private void Application_Activated(object sender, ActivatedEventArgs e) { LoadSettings(); }
private void Application_Deactivated(object sender, DeactivatedEventArgs e) { SaveSettings(); }
private void Application_Closing(object sender, ClosingEventArgs e) { SaveSettings(); }
|
Here are the LoadSettings
and SaveSettings methods. Both methods
obtain an IsolatedStorageSettings
object. Like the State property of PhoneApplicationService, the IsolatedStorageSettings
object is a dictionary. One method in the program loads (and the other
saves) the Color property of the BackgroundBrush
property with code that is similar to what you saw before.
Example 3. Silverlight
Project: SilverlightIsolatedStorage File: App.xaml.cs (excerpt)
void LoadSettings() { IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
Color clr;
if (settings.TryGetValue<Color>("backgroundColor", out clr)) BackgroundBrush = new SolidColorBrush(clr); }
void SaveSettings() { IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
if (BackgroundBrush is SolidColorBrush) { settings["backgroundColor"] = (BackgroundBrush as SolidColorBrush).Color; settings.Save(); } }
|
And finally, here’s the new
MainPage.xaml.cs file. This file—and any other class in the program—can
get access to the App
object using the static Application.Current property and casting it to an App. The constructor of MainPage obtains the BackgroundBrush property from the App class, and the OnManipulationStarted
method sets that BackgroundBrush
property.
Example 4. Silverlight
Project: SilverlightIsolatedStorage File: MainPage.xaml.cs (excerpt)
public partial class MainPage : PhoneApplicationPage { Random rand = new Random(); int numTaps = 0; PhoneApplicationService appService = PhoneApplicationService.Current;
public MainPage() { InitializeComponent(); UpdatePageTitle(numTaps);
// Access App class for isolated storage setting Brush brush = (Application.Current as App).BackgroundBrush;
if (brush != null) ContentPanel.Background = brush; }
protected override void OnManipulationStarted(ManipulationStartedEventArgs args) { SolidColorBrush brush = new SolidColorBrush(Color.FromArgb(255, (byte)rand.Next(256), (byte)rand.Next(256), (byte)rand.Next(256))); ContentPanel.Background = brush;
// Save to App class for isolated storage setting (Application.Current as App).BackgroundBrush = brush;
UpdatePageTitle(++numTaps);
args.Complete(); base.OnManipulationStarted(args); }
void UpdatePageTitle(int numTaps) { PageTitle.Text = String.Format("{0} taps total", numTaps); }
protected override void OnNavigatedFrom(NavigationEventArgs args) { appService.State["numTaps"] = numTaps;
base.OnNavigatedFrom(args); }
protected override void OnNavigatedTo(NavigationEventArgs args) { // Load numTaps if (appService.State.ContainsKey("numTaps")) { numTaps = (int)appService.State["numTaps"]; UpdatePageTitle(numTaps); } } }
|
Because that background
color has been upgraded from transient page data to an application
setting, references to it have been removed in the OnNavigatedFromOnNavigatedTo overrides.