January 2012
Volume 27 Number 01
Windows Phone - Your First Windows Phone Application
By Jesse Liberty | January 2012
The trick in writing a first Windows Phone application is to build something interesting enough to be meaningful, yet simple enough to actually get underway. Toward that end, I’ll walk you through creating a simple utility that I use every day: NoteToMe. The idea is that you can enter a message and send it to yourself by pressing one button, as shown in Figure 1.
Figure 1 The NoteToMe Interface
Note that this article will touch on a number of topics, each of which will be expanded upon at some length in subsequent articles. These topics include:
- Creating the layout of the application
- Storing and retrieving data from Isolated Storage
- Events and event handling
- Creating and running tasks (launchers and choosers)
Before you can begin, you’ll need to download the tools from create.msdn.com. If you’ve already unlocked your phone but not yet upgraded to Windows Phone 7.5 (“Mango”), now is the time to do so; Mango brings hundreds of new features to the Windows Phone OS.
Getting Started
Like many Windows Phone developers, I’ve come to believe that the best tool for creating Windows Phone applications is a combination of Visual Studio (for code) and Expression Blend (for everything else). Thus, we’ll begin by opening Expression Blend and creating a new application named NoteToMe, based on the Windows Phone SDK 7.1.
Let’s start by changing the application title. Click on the title, and in the Properties window find the Text property for that control. The Metro design guidelines (the design guidelines for Windows Phone) call for the title to be in all caps, so change the title to NOTE TO ME.
Click on the page title and hit Delete to remove it.
To create the layout, you’ll need a small row near the top of the page. Click in the margin to bring up a guideline that helps you visually select where to place the row, as shown in Figure 2.
Figure 2 Placing the Top Row of the Layout
Of course, you can set the row size by hand directly in the XAML:
<Grid.RowDefinitions>
<RowDefinition Height="1*"/>
<RowDefinition Height="9*"/>
</Grid.RowDefinitions>
The asterisk after the value indicates relative sizing—in this case 1:9. That is, the first row will be one-ninth of the size of the second row.
Adding Three Controls to the StackPanel
The top row will have three controls in it, side by side:
- A TextBlock acting as a label
- A TextBlock to hold the e-mail address
- A Button to send the message
This design is shown in Figure 3.
Figure 3 Three Controls in the Top Row
You can’t put three controls into a single column of a row without putting them inside some sort of organizing container. I’ll use a StackPanel whose orientation has been set to horizontal—StackPanels stack on top of each other or next to each other.
To create a StackPanel, click on the tiny white arrow next to the Layout control on the toolbar as shown in Figure 4.
Figure 4 Adding a StackPanel
Click on the StackPanel to select the control. Now drag a StackPanel into the row and set its vertical and horizontal alignment to stretch and its margins to zero in the Layout window as shown in Figure 5.
Figure 5 Placing the StackPanel
Add the TextBlock, setting its font size to 32, and its text to To. Now drag a TextBox onto the StackPanel. (Note the important but subtle difference between a TextBlock, for displaying text, and a TextBox, for text input.) Name this TextBox Address. Finally, add a button to the StackPanel, name it Send and set its Content to Send.
The XAML this produces is shown in Figure 6.
Figure 6 Designing the StackPanel with XAML
<StackPanel
Margin="0"
Orientation="Horizontal">
<TextBlock
Margin="0,8"
TextWrapping="Wrap"
Text="To"
Width="42"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="32" />
<TextBox
x:Name="Address"
Margin="0,0,0,-7"
TextWrapping="Wrap"
Text="foo@bar.com"
Width="293" />
<Button
x:Name="Send"
Content="Send"
Margin="0,4,0,0"
Width="124"
Click="Send_Click" />
</StackPanel>
Notice the Send button has a Click=“Send_Click” property. You create this by clicking on the button, then in the Properties window, you click on the Events button, as shown in Figure 7.
Figure 7 The Events Button
This opens all the events for the button. Find the click event and double-click. The button is updated with the event, and you’re placed in the code editor (either in Blend or in Visual Studio, depending on how you have Blend set up) for that event handler. For now, you can leave this event handler as is:
private void Send_Click( object sender, RoutedEventArgs e )
{
}
Adding the Message Control
Click on the TextBox control in the toolbar and then drag a TextBox out to fill half of the remaining page (we’re leaving the other half for the keyboard, which will appear when it’s time to enter something in the TextBox). Set the HorizontalAlignment to Stretch, the VerticalAlignment to Top, the margins to 0. Set the Width to Automatic and the height to 244. You can do all this by eye as you resize the TextBox, or you can draw the TextBox roughly in place and set the properties in the Properties window as shown in Figure 8.
Figure 8 Adding the TextBox
Writing the Code
With the controls in place, you’re ready to work on the logic of the program. You should see a tab called Projects in the upper left corner. After saving all your changes, click the Projects tab, then right-click on MainPage.xaml.cs and select Edit In Visual Studio, as shown in Figure 9.
Figure 9 Getting Ready to Write the Code
The Specification
My (self-imposed) specification says you shouldn’t have to fill in the To field each time you use the program; the To field should be prepopulated with whatever was in the To field the previous use.
Moreover, when you click Send, a new e-mail message should be prepared for your e-mail program, with all the fields prepopulated so that you can just press Send or, optionally, edit the message and then press Send.
Using Isolated Storage
To preserve the contents of the To field across usages of the application, you need to store the contents somewhere on the phone. This is what Isolated Storage is for: persisting data when the application is closed. As its name implies, Isolated Storage allows your application to store data isolated and protected from data stored by other applications. Using Isolated Storage is fairly straightforward.
First, add the using statement:
using System.IO.IsolatedStorage;
Declare a member variable of type IsolatedStorageSettings and a constant string to act as a key into the Isolated Storage dictionary so you can store and retrieve the e-mail address:
private IsolatedStorageSettings _isoSettings;
const string IsoKey = "EmailAddress";
Initialize the _isoSettings member in the constructor:
_isoSettings = IsolatedStorageSettings.ApplicationSettings;
Storing and Retrieving the E-mail Address
The two tasks related to Isolated Storage are storing the string and retrieving it. Storing it is best done as you leave the page. When you leave any Windows Phone page, the method OnNavigatedFrom is called. You’re free to override it, and one good reason to do so is to store data in Isolated Storage, like this:
protected override void OnNavigatedFrom(
System.Windows.Navigation.NavigationEventArgs e )
{
_isoSettings[IsoKey] = Address.Text;
base.OnNavigatedFrom( e );
}
Now you have the e-mail address stored in the _isoSettings dictionary under the IsoKey key. When you return to the page, you can restore this setting. I do this by calling the private helper method RestoreEmailAddress from the constructor:
private void RestoreEmailAddress()
{
if (_isoSettings.Contains( IsoKey ))
Address.Text = _isoSettings[IsoKey].ToString();
}
Notice that I test for the existence of the key in Isolated Storage before trying to restore it—this averts a KeyNotFound exception the first time I run the program. Remember, the first time you run the program you haven’t yet stored anything in Isolated Storage.
When the program is first started, there’s nothing in the Address field. Once the user puts an e-mail address in the address field, that address is stored in Isolated Storage and restored the next time the program is run. If the user changes the address, that new address is the one restored.
Tasks
Windows Phone 7.5 supports a number of tasks for interacting with built-in phone applications (mail, contact list, the camera and so forth). There are two types of tasks: Launchers and Choosers. Choosers are used to select information and return it to your program (to obtain an e-mail address from the contact list, for example). Launchers are used to launch a program that doesn’t return data.
In this case, you have everything you need to send the message, so you can call the e-mail Launcher and supply the required fields. When you call Show on the e-mail Launcher, the e-mail application will be launched with your data, but you won’t get any data back (which is fine; you don’t need any).
After the e-mail is sent, you’re returned to the program in case you want to send another message.
All of the work of creating the Launcher is encapsulated within the click event handler for the Send button. Let’s begin by creating an instance of the EmailComposeTask (the Launcher). Fill in the fields and call Show. That’s all there is to it:
private void Send_Click( object sender, RoutedEventArgs e )
{
EmailComposeTask emailComposeTask = new EmailComposeTask();
emailComposeTask.Subject = "Send To Me";
emailComposeTask.To = Address.Text;
emailComposeTask.Body = Message.Text;
Message.Text = String.Empty;
emailComposeTask.Show();
}
When you call Show, the subject, address and body of the message are passed to your e-mail application. If you have more than one e-mail application, you’re asked which one you’d like to use. A properly addressed and formatted e-mail message is created, ready for you to send.
The Application Lifecycle
If users could be relied on to never interrupt their use of your application until they sent the message, you’d be done. In reality, though, users will stop right in the middle of composing a message and launch a different application. When they return, they won't be happy if the work they did is gone.
To know how to protect against this, you need to understand a bit about the lifecycle of an application, and how you can preserve state while still supporting one of the most powerful features of Mango: Fast Application Switching.
When your application is launched (say from the Start menu), the Application Launching event is fired. Once the application is started, and every time the user navigates to your page, the OnNavigatedTo method is called, after which your page will be in the Running state. If the user starts a new application, your application receives the Application Deactivated event and is put in the dormant state. If the phone runs low on memory, your application may be tombstoned.
From either tombstoned or dormant, your application may be terminated or it may be restored. What we care about right now is what happens when your application is restored.
If your application is dormant, you not only don’t have to take any action when it’s restored, but you also don’t want to take any action; the state was preserved when the application was dormant, and it’s ready to go.
If your application was tombstoned, though, then you do want to restore your page state when the application returns so that it appears to the user that the application was running (or at least dormant) while it was switched away.
You therefore face two tasks:
- Save state when the page’s OnNavigatedFrom method is called.
- Potentially restore state when the page’s OnNavigatedTo method is called—restoring state if the app was tombstoned but not if it was dormant.
Saving State When the Page Is Going Away
Because you can’t know, when the page receives the OnNavigatedFrom, what state it will be in when it’s restored, you must store the state in case it will be needed. This is very easy to do: you use a State dictionary that’s very much like the Isolated Storage dictionary in its syntax, though you want to remember that the State dictionary is not written to permanent storage and is in fact destroyed when you exit the program or turn off the phone.
Let’s start by creating a constant string StateKey, which you’ll use as the offset into the State dictionary:
const string StateKey = "MessageState";
In the OnNavigatedFrom method, you’ll store the state (in this case, the contents of the MessageBox) into the State dictionary:
protected override void OnNavigatedFrom(
System.Windows.Navigation.NavigationEventArgs e )
{
_isoSettings[IsoKey] = Address.Text;
State[StateKey] = Message.Text;
base.OnNavigatedFrom( e );
}
Restoring State When the Page Is Created
When the OnNavigatedTo method is called, you don’t want to take any action to restore State if the app was dormant, but you do want to take action if it was tombstoned.
You can distinguish between the dormant or tombstoned state by setting a flag to false, and then setting it to true in the constructor. If the app is dormant, the constructor will not be called; if it was tombstoned, the constructor will be called (because it will be the first time it’s constructed), like so:
bool isNew = false;
public MainPage()
{
InitializeComponent();
isNew = true;
You can check that flag in OnNavigatedTo:
protected override void OnNavigatedTo(
System.Windows.Navigation.NavigationEventArgs e )
{
if (isNew)
{
if (State.ContainsKey( StateKey ))
{
Message.Text = State[StateKey].ToString();
}
}
isNew = false;
base.OnNavigatedTo( e );
}
This test saves the time it would otherwise take to restore the value from the State dictionary. You can test this by first running your program normally (in which case when you switch to another application your program will go dormant) and then forcing the program to be tombstoned. You can force your program to be tombstoned by right-clicking on the project, choosing Properties, choosing the Debug tab and checking the checkbox Tombstone upon deactivation while debugging.
When you run with this checked, you’ll see a noticeable pause when returning to the page because the state must be restored.
Final Overview
In this brief article, I’ve shown you how to write your first non-trivial Windows Phone application. I began by creating the application in Expression Blend, where I created a row and used a StackPanel to lay out the controls.
I then switched to Visual Studio to write the logic for the button’s event handler, and used Isolated Storage to persist the e-mail address. I used State memory to ensure that the application would restart properly after being tombstoned.
As noted, there’s much more to say on each of these topics, and they’ll be covered in detail in future articles.
Jesse Liberty is a senior developer-community evangelist on the Windows Phone team. Liberty hosts the popular Yet Another Podcast (jesseliberty.com/podcast), and his blog (jesseliberty.com/) is required reading. He’s the author of numerous best-selling books, including “Programming Reactive Extensions and LINQ” (Apress, 2011) and “Migrating to Windows Phone,” (Apress, 2011). You can follow Liberty on Twitter at twitter.com/JesseLiberty.
Thanks to the following technical experts for reviewing this article: Drew Batchelor and Cheryl Simmons