A Matter of State, Part 3

The previous 2 posts discussed using the Page and Application State Dictionaries to restore state following the application being tombstoned, as well as some other potential uses for the Application State Dictionary.  This final post in the series will cover the user of Isolated Storage from Windows Phone applications.

Isolated Storage Basics
Isolated Storage provides a virtual file system that allows an application (and in some cases applications) access to an (ahem) isolated area of persistent storage, usually disk-based.  The precise location is hidden from applications and is not meant to be human-readable/accessible.  The technique of using Isolated Storage to preserve state is one that is available across all flavors of .Net – there is support for Isolated Storage in the .Net Framework, in the Silverlight Runtime (both on the PC and the Mac), and in Silverlight for Windows Phone.  While many of the mechanics of using Isolated Storage APIs are similar between the platforms, there are some distinctions in Windows Phone that make its support for Isolated Storage unique.
At its core, data stored in Isolated Storage is placed in a scoped area called a Store.  Each runtime described above has access to a different collection of scopes for the stores, with .Net having access to the most (User, Domain, Assembly, Roaming, Machine, Application), and Silverlight having access to just two – Site and Application.  The Site scope allows shared storage access to all Silverlight applications on the same web domain, and the Application scope is identified by each unique Silverlight XAP file.
In Silverlight for Windows Phone, the Silverlight applications are not hosted on any web site, so the only Isolated Storage scope available in phone applications is per Application.  One important implication of this is that there is currently no way of sharing or exchanging data between applications via the phone file system.  Having gone over the concept of tombstoning, there’s also an implication that the technique of using Local Connections is not available for inter-application communication (if only one application can be running at a time, there’s nobody to communicate with.)  Taking this all one step further, the only way to communicate between different applications in Windows Phone is by using some form of internet-based storage.
The following code shows the basic procedure for writing data to Isolated Storage:
private void WriteData()
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
// Get the directories in the current Store
String[] directoryNames = store.GetDirectoryNames(“search pattern”);

// Get the files in the given directory path
String[] fileNames = store.GetFileNames(“search pattern”);
//Maybe create one or more directories
// Open a file stream (normal File.Open behavior)
using (IsolatedStorageFileStream fileStream = store.OpenFile(“file path”FileMode.Create))
using (StreamWriter writer = new StreamWriter(fileStream))
writer.WriteLine(“Some Data”);

  • Use the GetUserStoreForApplication call to get a reference to the application’s Isolated Storage file store
  • Using the store reference, it is possible to obtain a list of directories and/or files within the current store, as well as to create files and directories
  • Note that the process for creating files is the same as for regular files (specifying FileMode, etc.)
  • The result of an opened file is an IsolatedStorageFileStream object, which inherits from the FileStream class.
  • Once a reference to the IsolatedStorageFileStream object is available, code can be written against it as it can for pretty much any FileStream.  The example above wraps the stream with a StreamWriter which exposes a WriteLine that can be used to write a line of text into the stream (and hence the underlying file.)
  • Note that using blocks are being used to perform the necessary cleanup on Disposable objects throughout the process.
The following code shows the basic procedure for reading code from Isolated Storage:
private void ReadData()
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
if (store.FileExists(“file path”))
using (IsolatedStorageFileStream fileStream = store.OpenFile(“file path”FileMode.Open))
using (StreamReader reader = new StreamReader(fileStream))
String lineOfText = String.Empty;
while (null != (lineOfText = reader.ReadLine()))
  • Get a reference to the application’s Isolated Storage file store
  • Using the store reference, check to see fi the desired file exists
  • If the file exists, open the file for reading, which returns an IsolatedStorageFileStream object, which inherits from the FileStream class.
  • Once a reference to the IsolatedStorageFileStream object is available, code can be written against it as it can for pretty much any FileStream.  The example above wraps the stream with a StreamWriter which exposes a ReadLine that can be used to read a line of text at a time from the stream (and hence the underlying file.)
Within the System.IO.IsolatedStorage namespace, there is a “helper class” that reduces some of the work required for routine Isolated Storage tasks.  Much like the Application and Page State Dictionaries, the IsolatedStorageSettings class exposes a Dictionary of objects that uses string values for keys.  The IsolatedStorageSettings class is accessible as a singleton through the IsolatedStorageSettings.ApplicationSettings property (note that “regular Silverlight” also exposes IsolatedStorageSettings.SiteSettings for site-scoped storage.)
The following code shows writing and reading from the ApplicationSettings dictionary:
private void WriteSettingsData()
IsolatedStorageSettings.ApplicationSettings[“key”] = value;
private void ReadSettingsData()
if (IsolatedStorageSettings.ApplicationSettings.Contains(“key”))
value = IsolatedStorageSettings.ApplicationSettings[“key”];
Many possibilities are available for storing and retrieving data through Isolated Storage beyond simply reading and writing text using the StreamWriter and/or IsolatedStorageSettings.  These range from using Xml to hold serialized objects through custom database implementations, including my Wintellect colleague Jeremy Likness’s
Sterling Object-Oriented database and the Codeplex implementation/port of Sqlite.  Like most file systems, there are concerns regarding the quantity and size of items in any given folder, and there is a great discussion here on the performance behavior of Isolated Storage in Windows Phone under load.

Another important distinction between Isolated Storage for Silverlight and Isolated Storage for Silverlight for Windows Phone is that whereas there are user quotas in “regular” Silverlight (1 MB max for browser-based apps before the user must be asked if they would like to increase the quota, and 25 MB for out-of-browser apps), there are no storage quotas in place for Silverlight for Windows Phone applications.  Storage space is limited by the amount of storage space available on the device itself.
Not only is there no quota for the amount of storage that any one application can consume, there is also no File Explorer or WinDirStat equivalent for the phone to determine how much space is being consumed by any one application.  Although there’s no way to know which application may be consuming all of the available space on a device, if an application is chosen for deletion, when an application is uninstalled from the phone (locate the shortcut in the application list, hold down the application icon, and in the context menu that appears, choose uninstall) its isolated storage contents are deleted and the space they occupied is recovered.
Figure 1- Prompt When Uninstalling an Application
To determine the total amount of space remaining on disk, the IsolatedStorageFile instance offers an AvailableFreeSpace property.  With “traditional Silverlight”, this returns the amount of space remaining in the current quota.  Since Silverlight for Windows Phone does not have quotas, the AvailableFreeSpace property will return the amount of storage space remaining on the device.
In the following screenshots, an application was created that wrote a large amount of data to Isolated Storage.  A second application was written to show the amount of drive space remaining.  In the first screenshot, the storage application has not yet written its data to disk.  In the second screenshot, it has written data to disk, as can be seen by the reduced amount of available free space remaining.  Finally, in the third screenshot, the storage application has been uninstalled and its storage space has been reclaimed.  (Note that the extra space appearing in the third screenshot is most likely due to the additional space received by the removal of the Silverlight XAP file in addition to the content in Isolated Storage.)
Figure 2- Before Saving Large File
Figure 3- After Saving Large File
Figure 4- After “Big File” Application is Uninstalled
Knowing this about uninstallation, the next logical question usually deals with updating.  When an application is updated (a new version is placed in the Marketplace), the data in Isolated Storage is retained.  It is up to the application developer(s) to handle issues related to the handling of versioning with any previous application versions’ contents in Isolated Storage.

While Isolated Storage is the only one of the three state-preservation mechanisms discussed that can work across multiple launches of the same application (and hence beyond Tombstoning), it is certainly usable for Tombstoning scenarios, and is absolutely necessary in some cases, such as when the amount of data to be stored exceeds the limitations imposed by the other techniques.  Because of the performance implications of Isolated Storage (discussed in the previous article in the series, ~30% to ~55% slower) and the possibility of larger amounts of data, there are important time limits that need to be discussed.
First of all, as stated here in the MSDN documentation, if an application takes more than 10 seconds to launch, the application may be terminated by the operating system.  Furthermore, the Windows Phone Application Certification Requirements state that in order to pass the certification process, an application must render its first screen “within 5 seconds after launch” (5.2.1a), and must be responsive to user input “within 20 seconds after launch” (5.2.1b)  Finally, an application must conclude the Activated and Deactivated events within 10 seconds. (5.2.3)  As a result, it may be beneficial to consider breaking the content in Isolated Storage into smaller files that are accessed as needed (instead of big-load-up-front), background threads be used for loading large content at startup, and similar consideration be employed when saving data.
With these time considerations in mind, the key application lifetime events include:
  • Launching – Raised when a new instance of the application is launched (and will not be raised if the application is being activated following tombstoning.)
  • Closing – Raised when the application is terminated.  In Silverlight applications, this only occurs when the user uses the Back button past the first page in the application’s BackStack (and will not be raised when the application is being tombstoned.)
  • Deactivated – Raised when the user navigates away from the application (and in most cases, is tombstoned.)
  • Activated – Raised when the user returns to an application after it was deactivated.
Because both Deactivated and Closing (under most circumstances) result in the application being terminated and in-memory state being destroyed, it is important to ensure that state is appropriately saved and restored in both circumstances.  State information retrieved when an application is initially launched is not automatically preserved or restored.  For that reason, it is not atypical to see the Launching/Activated and Closing/Deactivated event handlers call into a common pair of methods (such as RestoreState and SaveState, respectively) to deal with common content.

In Closing
In this series, the posts focused on mechanisms for preserving state in Windows Phone Silverlight applications.  The key concepts presented included:
I hope that this coverage has helped to illustrate the benefits and limitations of each.

A Matter of State, Part 2

The previous post discussed using the Page State Dictionary to restore a page’s state when navigating back to that page following the application being tombstoned. This post will discuss the use of the Application State Dictionary, and the final post in the series will discuss using Isolated Storage.

The Application State Dictionary

The Application State Dictionary has a broader scope for availability than the Page State Dictionary, but still has some similar limitations. It is also implemented as an IDictionary<String, Object>, and is exposed through the PhoneApplicationService instance’s State property. The current instance of the PhoneApplicationService is usually accessed through the class’s Current static property – eg PhoneApplicationService.Current. Any objects stored in the Application State Dictionary need to be serializable. It is important to note that if an item is added to the dictionary when debugging, an ArgumentOutOfRangeException will be raised, but at runtime this exception is silently ignored.

Although the documentation does not call out any specific size limitations, empirical testing has shown there is one of about 1.5MB (it actually varies between the emulator and an actual device.) Storing data larger than that will result in an unhandled COM Exception with the message “The client who called IAccessControl::IsAccessPermitted was the trustee provided to the method” [sic]. This error does not happen immediately, but instead happens when the application is tombstoned, after the Application’s Deactivated event.

The contents of the Application State Dictionary can only be accessed within or after the application’s Activated event has been raised and within or before the application’s Deactivated event has been raised. Any attempt to access the contents outside of these times will result in an InvalidOperationException being thrown. Just like the Page State Dictionary, once these limitations are understood, the use of the Application State Dictionary is straightforward.

private void Application_Deactivated(Object sender, DeactivatedEventArgs e)
PhoneApplicationService.Current.State[“MyStuffToSave”] = value;

private void Application_Activated(Object sender, ActivatedEventArgs e)
if (PhoneApplicationService.Current.State.ContainsKey(“MyStuffToSave”))
value PhoneApplicationService.Current.State[“MyStuffToSave”];


Because the PhoneApplicationService is available throughout the application via the PhoneApplicationService.Current static property, the Application State Dictionary is available throughout most of the application (though it usually wise to respect proper architectural boundaries and hence be aware of what layer it is being called from.) In that light, the Application State Dictionary can be seen as a kind of globally-scoped collection of name-value pairs.

Both of the State Dictionaries keep their data in memory as opposed to Isolated Storage, which uses the phone’s file system. As a result, access to data is significantly faster. Some quick testing showed this to be ~30% faster on the emulator, and ~55% faster on an actual device, though individual devices are likely to report other results due to hardware differences.

There are some interesting scenarios that this state repository offers, including:

  • Remembering page control values for returning forward to a page
  • Passing data between pages that is too complex to pass via a simple QueryString parameter (though the key to the value in the dictionary may certainly be passed in the QueryString), without declaring a global variable to hold the data.
  • Remembering application-wide settings for restoration after a tombstoned application is reactivated

To use the Application State Dictionary to set page values following navigation, instead of using the Page State Dictionary to store a control’s state when leaving a page and to restore the state when returning to the page, the Application State Dictionary can be used, as illustrated in Figure 1, below.

Figure 1

  • The “Go to Page 2” button is used from Page 1 to navigate to Page 2.
  • In Page 2, the user enters “User State 1” in the first textbox and “User State 2” in the second textbox.
  • When the user presses the Back Button from Page 2, the value of textbox 1 is put into the Application State Dictionary during the OnNavigatedFrom method
  • The user presses the “Go to Page 2” button again. In the page’s OnNavigatedTo method, the Application State Dictionary is interrogated to see if it has a value, and if so, the value is applied to the first textbox
  • Note – if there is the possibility that the page whose state is being saved can be used in different contexts (for example, a page that shows details for a selected item on the first page), the key value for the setting should likely include the context, in order to properly resolve which value is to be displayed.

Another scenario where the Page State Dictionary can be used is for passing complex objects between pages. Remembering that navigation between pages on the phone does not involve actually creating an instance in code of the page to navigate to – the call to the Navigate method of the NavigationService with the Uri of the page to navigate to takes care of creating the new page instance. Although data can be communicated between pages via a QueryString parameter, complex data may not translate well to QueryString values. Using the Application State Dictionary to supplement the exchange of data between pages via QueryString information is illustrated in Figure 2.

Figure 2

  • The “Go to Page 2” button is used from Page 1 to navigate to Page 2
  • A value is added to the Application State Dictionary. Remember that the item must be serializable to be placed in the Application State Dictionary.
  • The key for the value added to the Application State Dictionary in the previous step is added as a ValueKey parameter to the Uri provided for the Navigate command
  • In the Page 2 OnNavigatedTo method, the NavigationContext is interrogated for the QueryString ValueKey parameter. If the key is found, its value is used to retrieve the serialized object from the Application State Dictionary
  • Page 2 is then able to interact with the object that was passed to it from Page 1

Finally, the most common use of the Application State Dictionary is to preserve and restore application-scoped state when an application is tombstoned and reactivated. This process is shown in Figure 3.

Figure 3

  • At some point the application is tombstoned as a response to some user action (pressing the Start or Search button, etc.)
  • In the Application’s Deactivated event handler, the application’s state is stored in the Application State Dictionary.
  • The user presses the Back button to return to the application.
  • In the Application’s Activated event handler, data is read form the Application State Dictionary and used to restore the application state.

Another important note is that the application’s Deactivated event handler must complete in 10 seconds or less, or the application might be forcibly terminated and may be unavailable via the back stack.

The Application State Dictionary and Choosers

The term “Chooser” is applied to Windows Phone API elements that allow the user to launch an application that is part of the Windows Phone system in order to make a selection, and upon completion, return that item to the calling program by raising a Completed event. Choosers include:

  • The CameraCaptureTask launches the Camera application and returns a PhotoResult object (which includes a stream that contains the image data.)
  • The EmailAddressChooserTask launches the Contacts application and returns an EmailResult object (which includes the selected email address as a string.)
  • The PhoneNumberChooserTask launches the Contacts application and returns a PhoneNumberResult object (which includes the selected phone number as a string.)
  • The PhotoChooserTask launches the Photo Picker application and returns a PhotoResult object (outlined above.)
  • The SaveEmailAddressTask saves the provided email address to the Contacts list (it does not actually return any data, other than an indication as to whether the address was added.)
  • The SavePhoneNumebrTask saves the provided phone number to the Contacts list (it does not actually return any data, other than an indication as to whether the address was added.)

Choosers are distinguished from Launchers, which allow the application to launch certain Windows Phone system applications in a fire-and-forget model. Some Launchers include the WebBrowserTask, which opens a web browser with the given address, and the EmailComposeTak, which displays a new email message with given values for recipients, message subject, and message body, and there are several additional Launchers.

The guidance given for using Choosers advises that the Chooser’s completed event should be subscribed in the Page’s constructor. This is because when the Chooser is invoked, the running application *might* be tombstoned, losing the event subscription as part of that process. (There is documentation indicating that Choosers have been optimized to not always tombstone an application. Ssee the bottom of the article at http://msdn.microsoft.com/en-us/library/ff817008%28v=VS.92%29.aspx for a description of the optimization that may bypass this…still, since there is a grain of unpredictability, the action needs to be handled as if tombstoning is a certainty.)

The problem with Choosers is that the Completed event is actually raised before the page’s OnNavigatedTo method is called. This means that the Page State Dictionary is not available when responding to a Chooser’s completed event, and attempting to access it will result in an InvalidOperationException. Imagine the following scenario:

  • A page displays a list of items
  • The user can select an item in the list and press a Send button
  • The Send button invokes a Chooser to allow the user to select an email address
  • On completion of the Chooser, the page will use the EmailComposeTask Launcher to compose an email to the selected address with the text from selected item in the email’s body.

Using the Application State Dictionary, the selected item in the list can be saved off while the Email Address Chooser (potentially) tombstones the application and restored when the application returns with the chosen address, as the following code illustrates:

private readonly EmailAddressChooserTask _chooser = new EmailAddressChooserTask();

public Page1()
    _chooser.Completed += HandleEmailAddressChooserCompleted;

private void SendButton_Click(Object sender, RoutedEventArgs e)
if (SelectionListBox.SelectedItem == nullreturn;
    PhoneApplicationService.Current.State[“InterestingItemToSend”] = SelectionListBox.SelectedItem.ToString();

private void HandleEmailAddressChooserCompleted(Object sender, EmailResult e)
if (e.TaskResult == TaskResult.OK)
     var emailComposeLauncher = new EmailComposeTask
             To = e.Email,
                Subject = “This is Interesting”,
                Body =
                 “Check out this interesting thing” +


So now we’ve seen how the Application State Dictionary adds to the functionality offered by the Page State Dictionary, including exchanging information through several parts of an application, saving application state information across tombstoning events, and how it can be used to allow Choosers to get access to page state information when they return control to the calling application. The next installment will explore support for Isolated Storage in the Windows Phone system.

A Matter of State, Part 1

The Windows Phone platform offers several mechanisms for preserving your application’s state…the key is knowing which one to use when, and why. I’m going to try to provide some guidance to help answer those questions.
First things first – there are 3 key mechanisms provided for saving application state on the phone (4 if you count writing to some kind of cloud storage, but that’s beyond the scope of this discussion.) There are two state dictionaries, which under the right circumstances are saved and restored automatically, and then there is IsolatedStorage. This discussion will explore the uses of each one, with this post focusing on the Page State Dictionary.
The Page State Dictionary
This is by far the narrowest in scope of the 3 state-saving mechanisms. It is implemented as an IDictionary<String, Object>, and is accessible through a PhoneApplicationPage’s State property. To be stored in this collection, the objects that are placed must be serializable. There is also a limitation of how much data can be stored using this mechanism, with up to 2MB available per page and up to 4MB available for the entire application.
The contents of the Page State Dictionary can only be accessed within or after the page’s OnNavigatedTo method has been called and within or before the page’s OnNavigatedFrom method has been called. Any attempt to access the contents outside of these times (for example in the page’s constructor) will result in an InvalidOperationException being thrown.
Outside of these limitations, use of the Page State Dictionary is quite straightforward. When leaving the page (or any time prior), the data to be retained is written to the Page State Dictionary:
protected override void OnNavigatedFrom(NavigationEventArgs e)
State[“UserStateData”] = UserStateTextBox.Text;
When returning to the page, the Page State Dictionary is interrogated for the value and, if present, the value is applied to the control.
protected override void OnNavigatedTo(NavigationEventArgs e)
if (State.ContainsKey("UserStateData"))
UserStateTextBox.Text = (String)State["UserStateData"];
To understand when the Page State Dictionary is useful (necessary?), it is important to understand the Page navigation model in Windows Phone applications. To that end, a simple application is used, consisting of 3 pages. Page 1 and Page 2 each include a button that navigates to the next page. The second page (pictured below) includes 2 textboxes and the overrides for the OnNavigatedFrom and OnNavigatedTo methods listed above, which persist and retrieve the value of only the first textbox into/from the Page State Dictionary.
Figure 1
When switching between pages using the Navigate method from the NavigationService class, a new instance is created of the page defined by the Xaml file referenced in the method’s “source” parameter. This happens every time. When doing explicit navigation (eg – a Url is provided to the Navigate method), a new page instance is created. Figure 2 illustrates this concept of new page instance creation.
Figure 2
  • The “Go to Page 2” button is used from Page 1 to Navigate to Page 2 with the code NavigationService.Navigate(new Uri(“/Page2.xaml”UriKind.Relative));
  • This first instance of Page 2 is created with its own Page State Dictionary. The user enters the phrase “User State 1” into the first textbox and “User State 2” into the second textbox, and following the OnNavigatedFrom code above, the value of the first textbox is put into the Page State Dictionary when the user uses the Back Button to navigate back to Page 1.
  • Now the user presses the “Go to Page 2” button again. This causes a completely new instance of Page 2 to be created, with its own Page State Dictionary. The value placed in the previous Page 2 instance’s Page State Dictionary is not preserved, resulting in both textboxes being empty.
Conversely, using either the Back Button or the NavigationService.GoBack method to navigate back to a page in the phone’s Back-Stack will not create a new instance of the page, but will instead use the original instance (there is an important exception to this, which will be discussed momentarily.) This is illustrated in Figure 3.
Figure 3
  • The “Go to Page 3” button is used from Page 2 to navigate to Page 3. In the OnNavigatedFrom method, the value of the first textbox is put into the Page State Dictionary.
  • The first instance of Page 3 is created. The user uses the Back Button to navigate back to Page 2.
  • The original instance of Page 2 is displayed, with the text in both textboxes still being displayed (even though only one textbox’s value was put into and retrieved from the Page State Dictionary.)
It is worth noting that there is no Forward button to complement the Back button on Windows Phone devices, and calls to the NavigationService.GoForward method will result in an exception.. This is because the current version of the Windows Phone does not maintain any “Forward Stack.”
So, if the Page State Dictionary is specific to an instance of a PhoneApplicationPage object and cannot be used for repeated explicit navigations to a specific page (as seen in Figure 1), and during navigation using GoBack or the BackButton, it has no effect on whether or not state is preserved (as seen in Figure 2), what good is it? The answer revolves around Tombstoning.
Tombstoning is the process in the Phone Application lifecycle where one application is terminated anytime another application is launched. A full treatment of Tombstoning is beyond the scoped of this discussion, but further information is available at http://msdn.microsoft.com/en-us/library/ff817008%28v=VS.92%29.aspx. The key concept to be aware of is that when an application is tombstoned, it is terminated and any in-memory state information is lost except for what was written to the State Dictionaries and any information written to disk via Isolated Storage. Likewise, an application that has been tombstoned can be reactivated when its entry in the Back Stack is reached using the phone’s Back Button (or via a Chooser action, as will be seen is a subsequent post.) The Page State Dictionary provides a mechanism for restoring a page’s state when it is re-invoked after the application has been tombstoned. This process is illustrated in Figure 4.
Figure 4
  • The “Go to Page 3” button is used from Page 2 to Navigate to Page 3. In the OnNavigatedFrom method, the value of the first textbox is put into the Page State Dictionary (same as the previous example.)
  • The first instance of Page 3 is created. The user launches another application (via pressing the Start or Search Buttons on the Phone, etc.) This tombstones the current application.
  • The user finishes using the other application and presses the Back Button, re-activating the tombstoned application and creating a new instance of Page 3
  • The user presses the Back button to go back to Page 2. A new instance of Page 2 is created, but it does have access to the original Page State Dictionary.
  • The value of the first textbox (“User State 1”) is rehydrated from the entry in the Page State Dictionary during the OnNavigatedTo method. The data entered into the second text box is lost.
So in the end, the main reason to use the Page State Dictionary is to restore the state of the page when navigating Back to that page either immediately or at some point after the application has been tombstoned. However, if the application is tombstoned as a result of invoking a Chooser, things may be quite different, as will be seen in the follow-up to this post, which will go over the Application State Dictionary.

New Hampshire .Net (Concord) User Group Presentation Materials

I have uploaded the content from my Introduction to Windows Phone 7 Development with Silverlight talk at the New Hampshire (Concord) .Net User Group meeting last night in Concord. The content can be found here, and includes:

  • Presentation slides, which include the reference links I mentioned during the talk.
  • The sample code, broken into 2 projects. Because the Notification Services portion of the talk adds extra projects to the solution ad is a little more complex to build and launch, that portion has been broken out into its own separate zip file.

For the Notification Services portion of the demo, the web project should be launched first, followed by the phone project (since the phone app calls the web site to register its URL for receiving notifications.) If the solution is run with the web project set as the default start project, the application bits do get deployed to the phone, but the debugger is not hooked up (unless multiple startup projects are used.) If debugging of the phone app is desired, it can be achieved by right clicking on the phone project and selecting Debug / Start New Instance. Also, this time the Notification Services demo includes the Push Notification Server-Side Helper recipe.

As usual, I have “sanitized” the uploaded code content by removing my personal Bing Maps application key. For information on how to obtain your own map key, please check out the Bing Maps Developer Portal.

Many thanks to Patty Tomkins for organizing the user group and the event, the folks at NHTI for providing a great venue, Jim O’Neil from Microsoft for providing the Windows Phone swag, as well as to all of the attendees. We had some “minor technical issues” to overcome with getting the projectors set up (I need to remember to add a 10′ VGA cable to my standard presentation traveling kit), but once we hijacked another cable and got past that problem, everything went great.