LightTouch Enhancements–Popups and “Layered” Controls

While I am actively working on adding new functionality to the LightTouch library (such as adding the Pinch Gesture to bring parity with the GestureListener for Windows Phone from the Silverlight for Windows Phone Toolkit) for an upcoming release, a couple of issues came to light that made adding a new release appropriate.  As the title of this post suggests, these issues relate to support for touch in Popups (especially ChildWindow controls) and for controls where different layers of the control’s visual tree make use of different behaviors.

Support for Popups / Child Windows

At the heart of LightTouch is the Manipulation2DBehavior.  Much of the functionality behind this behavior is discussed here.  One of the basic methods’ responsibilities is to determine, based on the coordinates of the touch event, what controls are under that point and which of those controls have the Manipulation2DBehavior attached.  To do this lookup, the VisualTreeHelper.FindElementsInHostCoordinates function is used, with Application.Current.RootVisual supplied for the relative UIElement.  This is where difficulty with popups occurred.  Popup controls exist outside of the Visual Tree of the application’s RootVisual.  This can be seen in the following UI, with its Visual Tree as reported by Silverlight Spy.  Note how the Popup control appears as a sibling to the MainPage element.

image

image

So in order to locate the controls with behaviors in the popup, we have to use the Popup as the relative UIElement for the call to VisualTreeHelper.FindElementsInHostCoordinates.  Now to find the popup in the Visual Tree…this can be accomplished with the VisualTreeHelper.GetOpenPopups call.  Unfortunately, this call does not document how the list is populated relative to the Z-order of the ChildWindow (in case multiple ChildWindows are being displayed, issues of UI-propriety with this approach notwithstanding.)  Empirically, it seems that the topmost child window (if present) is the first in the list, so if any ChildWindows are being shown, we locate the first one in the list, and use it as the argument to FindElementsInHostCoordinates.  From there on, things progress as they had previously.

Supporting “Layers”

Shrek: “NO!  Layers.  Onions have layers.  Ogres have layers.   Onions have layers.  You get it?  We both have layers”
Donkey: “Oh, you both have layers.  Oh.  You know, not everybody likes onions.  What about cake?  Everybody loves cake!”
- Shrek (2001)

So what do I mean about layers?  In this case, I am referring to a situation where multiple related controls under a given point in a visual tree have Manipulation Behaviors attached.  An example would be a ListBox control with the ListBoxTouchScrollBehavior attached, and the underlying data template for the items in the list box having a GestureListener attached with a handler for a DoubleTap event.  The original implementation stopped at the first matching behavior, resulting in the ListBox scrolling, but ignoring the DoubleTap event.  The new implementation now identifies and processes all Manipulations under the given touch point.  This is similar to a Bubbling event, with a couple of key differences.  First, there is no notion of “handled.”  Second, the relationships do not have to exist in common branches of the same visual tree.

Available for Download

The latest code is up on CodePlex and the Alpha-2 release has been built based on these changes, which can be downloaded here.  I hope people find it helpful.

New Hampshire .Net (Seacoast) User Group Presentation Materials

I have uploaded the content from my Introduction to Windows Phone 7 Development with Silverlight talk at the New Hampshire .Net Seacoast User Group meeting last night in Portsmouth. 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.

I have also added a project that  shows the technique for “immediately” updating the application’s tile via a temporary Notification Services endpoint.  This is based on the code first presented here

The posted Slide Deck includes the slides that call out new content in the upcoming “Mango” release of WP7, and I have edited one slide to include one IMPORTANT new addition to the phone SDK that I forgot to previously include – support for Sockets.

Many thanks to Pat Tormey for inviting me to be the inaugural speaker for this new user group, as well as to Mark Mullin and Global Relief Technologies for providing a great site.  Also many thanks are deserved by the attendees, who asked some of the best questions I have gotten since I started doing these talks.

New for Windows Phone (Now) – the Async CTP

As is often the case when big events happen, sometimes some important announcements can get overlooked and/or overshadowed.  Mix 2011 certainly featured big news, including Silverlight 5 Beta, the Windows Phone 7.5 features, IE10, and the latest in the MVC framework.  However, in all of the hoopla, the release of the SP1 refresh of the Microsoft Visual Studio Async CTP SP1 Refresh, as well as some of the important changes, may have gone unnoticed.

There are a few important things to note regarding the Async CTP Refresh:

  • It includes an “As-Is” Go-Live license for use in production environments (albeit with some stern warnings about why you should really consider NOT using it in production code.)
  • It includes support for .Net, Silverlight 4, and Windows Phone 7.0.

Let me restate that last point.  The Async CTP works with Windows Phone 7 today.  No need to wait for the Mango update.

Now Just “await” a Minute…

As a CTP, and with the “As Is” license, there is no guarantee that this will eventually make it into the framework, and even if it does, it may take a very different form.  That being said, it is a great opportunity to see where things are headed and to offer feedback to the development team as to how to best shape this functionality to be as useful as it can be. 

That’s Nice.  How Long do I have to “await” to See Some Code?

So what do the Async tools bring to the table?  Among other things, it allows asynchronous code to be written without the “disruption” that currently occurs when that is being done today.  While a full discussion of asynchrony and the problems it solves and the new ones it presents are beyond the scope of this discussion, some brief coverage is merited.  Writing synchronous code today follows the pattern of “do something, wait for it to finish, then proceed.”  Altering this to be asynchronous (often) changes the pattern either the Asynchronous Programming Model/APM (“Call BeginXXX to start the operation, then EndXXX to wait for it to be completed”) or to the Event-Asynchronous Pattern/EAP (“start doing something, and raise an event that I am listening for when you are done.”)  When the completion of one asynchronous operation needs to trigger another one, code can get complicated and messy.  This situation is particularly apparent to those who use Silverlight and the related Silverlight for Windows Phone, as all I/O operations in Silverlight are inherently asynchronous.  The Async CTP brings a third model – the Task-based Asynchronous Pattern/TAP. 

The TAP model features the use of the async and await keywords to allow asynchronous code to be written in a much more linear fashion.  Under the covers, the compiler will generate all of the necessary “goo”, allowing the development to focus on the problem at a higher level.  The following code may help to visualize what this all means.

In the code that follows, a WebClient is spun up to return the data at a given URL.  The number of bytes in that data is returned as the result of the function.  This is the synchronous version of the code.

Code Snippet
  1. private void button1_Click(object sender, RoutedEventArgs e)
  2. {
  3.     var count = DoSomething();
  4.     MessageBox.Show(count.ToString());
  5. }
  6.  
  7. private Int32 DoSomething()
  8. {
  9.     var webClient = new WebClient();
  10.     var data = webClient.DownloadString(new Uri("http://www.wintellect.com/Consulting/Consultants/John-Garland"));
  11.     var results = data.Length;
  12.     return results;
  13. }

Note that this code blocks the UI when called, and cannot be used in Silverlight or Silverlight for Windows Phone applications.  So what if you don’t want to block the UI while retrieving the information (or better yet, what if you cannot, as is the case with Silverlight?)  Bring in asynchrony, but notice how it changes the nature of the function.  Where the desire had been to call a function to retrieve a result, now the function is called to eventually signal a response, which must be subscribed to by the calling code.

Code Snippet
  1. private void DoSomethingEAP()
  2. {
  3.     var webClient = new WebClient();
  4.     webClient.DownloadDataCompleted += HandleWebClientDownloadDataCompleted;
  5.     webClient.DownloadStringAsync(new Uri("http://www.wintellect.com/Consulting/Consultants/John-Garland"));
  6. }
  7.  
  8. private void HandleWebClientDownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
  9. {
  10.     var data = e.Result.Length;
  11.     MessageBox.Show(data.ToString());
  12. }

This is somewhat compressed and contained when inline lambda expressions are brought to bear, but the fundamental problem still exists.  The function has been modified because of its asynchronous implementation. 

Code Snippet
  1. private void DoSomethingEAPLambda()
  2. {
  3.     var webClient = new WebClient();
  4.     webClient.DownloadDataCompleted += (o, e) =>
  5.     {
  6.         var data = e.Result.Length;
  7.         MessageBox.Show(data.ToString());
  8.     };
  9.     webClient.DownloadStringAsync(new Uri("http://www.wintellect.com/Consulting/Consultants/John-Garland"));
  10. }

Now lets see how using the Async tools change things. 

Code Snippet
  1. private async void button1_Click(object sender, RoutedEventArgs e)
  2. {
  3.     var count = await DoSomethingAsync();
  4.     MessageBox.Show(count.ToString());
  5. }
  6.  
  7. private async Task<Int32> DoSomethingAsync()
  8. {
  9.     var webClient = new WebClient();
  10.     var data = await webClient.DownloadStringTaskAsync(new Uri("http://www.wintellect.com/Consulting/Consultants/John-Garland&quot;));
  11.     var results = data.Length;
  12.     return results;
  13. }

Note that the functions now much more closely resemble the initial synchronous version. 

I’m Tired of “awaiting”.  Get Me the Bits.

This was just a light overview.  There are many other combinations and applications for the TAP.  Hopefully, this was enough to pique some curiosity.  If interested, the download for the Microsoft Visual Studio Async CTP SP1 Refresh is available at http://msdn.microsoft.com/en-us/vstudio/async.  This includes documentation, samples, and walkthroughs.  The tools require Visual Studio 2010 SP1.  Check out Eric Lippert’s announcement of the release (and additional links) at http://blogs.msdn.com/b/ericlippert/archive/2011/04/13/refreshing-the-async-ctp.aspx.

Tech Valley .Net User Group Presentation Materials

I have uploaded the content from my Introduction to Windows Phone 7 Development with Silverlight talk at the Tech Valley .Net User Group meeting last night in Albany. 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.

Silverlight for Windows Phone Programming Tip – Be Sure to Scope Your SIP

Scope Your SIP – sounds painful, doesn’t it? Adding on to Jeff‘s series concerning WP7 Silverlight development tips, I figured it worthwhile to add another one. The SIP is the Software Input Panel – AKA the Phone’s onscreen keyboard. One of the handy features of the SIP is the ability to customize it to fit the needs of the textbox it is being displayed for – eg if you need to enter a phone number, why wrestle with a bunch of letter keys?
Figure 1- SIP default appearance (USA)
To do so, it is necessary to provide set the TextBox’s InputScope property to one of the values in the InputScopeNameValue enumeration, as pictured below:
<TextBox>
    <TextBox.InputScope>
        <InputScope>
            <InputScopeName NameValue="TelephoneNumber"/>
        </InputScope>
    </TextBox.InputScope>
</TextBox>
																			
Figure 2- SIP with TelephoneNumber Selected for the InputScope
Note that this is a little convoluted than the original description, which perhaps should have stated “it is necessary to provide the TextBox’s InputScope property with an InputScope object which contains the desired input scope name.” InputScope actually accepts a list of Names, of which only the first currently has any effect on the SIP display.
public sealed class InputScope : DependencyObject
{
    public InputScope();    
    public IList Names { get; }
}
If you want suggested word completions to appear as the user types letters, the only InputScope values that currently support completion are “Text” and “Chat.”
<TextBox>
    <TextBox.InputScope>
        <InputScope>
            <InputScopeName NameValue="Text"/>
        </InputScope>
    </TextBox.InputScope>
</TextBox>
																			
Figure 3- Showing Word Completion Suggestions with “Text” InputScope Selected

The New Phone Tools [are] Here! The New Phone Tools [are] Here!

With all due respect to Steve Martin’s hilarious portrayal of Navin R. Johnson and his quest for “his special purpose” in 1979’s The Jerk. Tonight Microsoft released the Windows Phone Developer Tools January 2011 Update, which can be downloaded here. In addition to the content in the new tools, there’s also some interesting other news concerning the availability of unsubsidized phones for purchase at Zones.com.

The New Tools

The big update item is the addition of Copy & Paste functionality. All TextBox and PasswordBox controls now get Copy and Paste functionality. This apparently applies to applications already in the Marketplace – once the update has been applied to the phone, Copy & Paste is available. The new behavior is bi-directionally compatible…controls within apps already on phones will automatically get Copy & Paste when the phone is upgraded, and apps compiled against the new Developer Tools will not misbehave on phones that have not yet received the update.

Note – the update is only for the developer tools – it is not yet available to be applied to devices – unlocked developer devices or otherwise. It only works in the Emulator.

Looking at the Copy & Paste behavior, when a TextBox has focus and a word is tapped, it gets a special highlight and the Copy Button appears. This works both with the mouse clicking in the emulator, as well as using touch when testing on a touch-enabled PC. There is no option for selecting portions of a word (eg to just select the “op” in the word “Copy”.) That last caveat is probably not that big of a deal, as selecting portions of a word on a touch device the size of a phone probably requires too much finesse. Multiple words can be selected – which is discussed below.

Figure 1- Selecting a Word and Displaying the Copy Button

To select multiple words, once the first word has been selected, it pressing and dragging on either edge allows the amount of text to be copied (in full word increments) to be adjusted

Figure 2- Extending the Selection to Multiple Words

Once text has been copied, a special Paste Button appears over the top of the onscreen keyboard (AKA Software Input Panel or SIP.) This is the same area where type-ahead suggestions appear.

Figure 3- The Paste Button on the Standard (US) SIP

Figure 4- The Paste Button on the SIP with InputScope Set to “TelephoneNumber”

In addition to TextBox and PasswordBox controls, the Copy & Paste functionality extends to controls that internally make use of TextBox controls, such as the Silverlight for Windows Phone Toolkit implementation of the AutoComplete Box. It also works for Text Input controls in web pages displayed in the WebBrowser control or in the phone’s Web Browser. However, in the WebBrowser control, the Copy Button can tend to “wander” a little bit…

Figure 5- Copy & Paste Controls in the Web Browser Control. Note the Odd Copy Button Placement

Paste is fairly straightforward. Select any control where the SIP appears and select the Paste Button. Paste is “single-shot” – there does not appear to be multiple Paste. Once the Paste Button has been pressed, the “clipboard” content is pasted into the target location, and the Paste Button is removed.

Two more quick notes about Copy & Paste:

  1. The “clipboard” persists outside of the application, so copied text can be used in other phone applications (for example, copying a Url from an application and pasting it into the browser’s address bar.) This also includes Tombstoning.
  2. The update also includes updates to the Pivot and Panorama controls. The update is for when TextBox controls have been added to panels within these controls, and aims to suppress inadvertent swipes when trying to copy text. Apps that have TextBoxes in Pivot or Panorama controls will need to be recompiled to get this change (they will still have Copy & Paste, though there may be some usability issues…)
    1. (Yes, the issue Jeff saw with Tombstoning is still there…)

Other Stuff in the New Tools

Other than the Copy & Paste feature, there are a couple of other things included with the update:

  • The Bing Maps Control has been updated for better gesture responsiveness
  • The update includes the Windows Phone Connect Tool, which is installed at <x86_ProgramFilesDir>\Microsoft SDKs\Windows Phone\v7.0\Tools\WPConnect. This tool can be used to connect a device for debugging when Zune is not running, which is necessary when debugging apps that use the media APIs.
  • The update includes the Windows Phone Capability Detection Tool, which is installed at <x86_ProgramFilesDir>\Microsoft SDKs\Windows Phone\v7.0\Tools\CapDetect. This tool is equivalent to the one used when applications are submitted to the Marketplace to inspect the app’s code so as to determine which capabilities are required by the app. These values are then used to replace the list in the app manifest. This tool can be used to preview what capabilities will be being detected before the app is submitted, in order to prevent issues like one (of admittedly several) issues seen by Shawn Wildermuth (see “Problem Part 4″) when an assembly that was inadvertently left in the application caused the app to report capabilities it actually didn’t need.

In addition to the tools, there is also a separate bug fix (VS10-KB2486994-x86.exe) that addresses a bug that existed whereby XAP files over 64MB could not be deployed by developers to physical devices for testing.

Issues with the Update

There is one known (at this time) defect with the update. Installing the update sets the default target for debugging Windows Phone Applications to be the “Windows Phone 7 Device”, even when a device is not installed. It is easy enough to change the value when Visual Studio barks at you, but it doesn’t “remember” the change, so it gets really old really fast.

Figure 6- The Default Debug Target for Phone Apps Changed to Windows Phone 7 Device

According to the Release Notes, the following steps are necessary in order to change this behavior (they work!)

  1. Close all Visual Studio and Windows Phone Emulator instances.
  2. Delete the contents of %LocalAppData%\Microsoft\Phone Tools\CoreCon.
  3. Restart Visual Studio.

Purchasing Unsubsidized Phones

In addition to publishing these new tools, apparently Microsoft has entered into a partnership with zones.com to allow the purchase of WP7 phones without going through one of the wireless carriers and the associated contract. The phones are locked to a specific carrier (it is not possible to take the Samsung Focus to T-Mobile in the US, for example), but they do allow developers to obtain devices for testing. As of the time of this writing, there is mention on the site of a “coupon code” which can be applied for some kind of discount, but I have no other information about any such offers. There are currently 3 phones available for purchase – the AT&T-offered HTC Surround ($500) and Samsung Focus ($525), and the T-Mobile HTC HD7 ($500). The zones.com developer purchase portal can be found at http://www.zones.com/windowsphonedeveloperpurchase.

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()
{
InitializeComponent();
    _chooser.Completed += HandleEmailAddressChooserCompleted;
}

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

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” +
                    PhoneApplicationService.Current.State[“InterestingItemToSend”]
            };
        emailComposeLauncher.Show();
    }
}

 

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.