31 Days of Windows Phone | Day #21: Silverlight Toolkit for Windows Phone

This post is Day #21 in a series called the 31 Days of Windows Phone.

After talking about the Map Control yesterday, it occurred to me that you might not be aware that there are TONS of controls available to you through the Silverlight Toolkit.  Today’s article addresses the Silverlight Toolkit for Windows Phone, specifically, but also check out the Silverlight 3 Toolkit as well.

What is a Toolkit?

The original toolkit for Silverlight 3 was a huge pile of extra controls that you could use in your projects.  The controls ranged from charting to accordions, date pickers to autocomplete boxes.  What’s awesome about this toolkit is that it’s completely compatible with our Windows Phone applications that use Silverlight.

The Silverlight Toolkit for Windows Phone 7 is a similar idea, but it only includes additional controls that would be used in a Windows Phone application.  It includes:

  • ContextMenu
  • DatePicker & TimePicker
  • GestureListener
  • ToggleSwitch
  • WrapPanel

I’m going to spend the rest of this article showing examples of each of the controls in this Toolkit, but I also highly encourage you to peruse the Silverlight 3 Toolkit as well.  There’s tons of controls, examples, and code that you can use in your projects.  I’m to cover the charting controls from that toolkit later in this series, but for those of you that are impatient, you can check it out on your own now.

ContextMenu Control

If you’ve had an opportunity to pin something to the Start page, you’ve seen the ContextMenu in action. Here’s what it looks like when I try to pin Internet Explorer to my Start menu in the emulator (tap and hold to show this menu):

contextmenucontrol

In order to make this menu appear, we need the ContextMenu control from the Silverlight Toolkit.  As with all of the examples in this article, we need to add the Silverlight Toolkit assembly to our project.  You can see it here:

addreference

Once we’ve added it, we’ll also need to add that namespace to the context of our XAML page.  To add this namespace, add this to the <phone:PhoneApplicationPage> tag at the top of your file:

xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"

Now we can get down to business.  Let’s take a common control that we might want to offer our users more options for, the Rectangle.  Perhaps we have a shape, image, icon, etc. that our users need to interact with.  Perhaps there is more than one thing you want to do with this Rectangle (think “right-click” menu).  By adding a ContextMenu to our Rectangle, we can pop a menu any time that our user taps and holds on that object.  This can be ANY XAML element, so you could even apply this to the background of your application, portions of a Panorama, or even Buttons.  Here’s how it’s applied in XAML:

<Rectangle Width="100" Height="100" Fill="Red">
	<toolkit:ContextMenuService.ContextMenu>
		<toolkit:ContextMenu>
			<toolkit:MenuItem Header="this is menu item 1" Click="MenuItem_Click" />
			<toolkit:MenuItem Header="this is menu item 2" Click="MenuItem_Click" />
			<toolkit:MenuItem Header="this is menu item 3" Click="MenuItem_Click" />
		</toolkit:ContextMenu>
	</toolkit:ContextMenuService.ContextMenu>
</Rectangle>

We basically tie in to the ContextMenuService, adding a ContextMenu to our specific control.  You can see that each item can also have a Click event, allowing us to tie these menu options back to our code.  Here’s a screenshot of my ContextMenu:

contextmenu

If you test this in your emulator, you might also notice that everything in the background zooms out a little, as if it’s dropping into the background, bringing the menu to the front and center of the user’s attention.  You might not want this behavior, so the <toolkit:ContextMenu> item has an additional attribute which is IsZoomEnabled.  Setting this to false will stop that zooming animation from happening automatically.

It’s that simple to add the equivalent of a right-click menu to our XAML elements.  This one will likely be the most used of the 6 controls (unless the GestureService  takes off).

DatePicker and TimePicker Controls

As I was preparing the code for this article, these two presented an interesting challenge for me.  They are SO straightforward simple that I just couldn’t figure out what I was doing wrong.  As it turns out, there’s a little magic involved.  I’ll explain that in a bit.  First, let’s talk about getting these controls on our page.  That’s the easy part:

<toolkit:DatePicker Value="7/22/1976" />
<toolkit:TimePicker Value="12:02 AM" />

When you add these controls to your page, they work as advertised.  They allow the user to select a date (starting with the initial date you provide…if you don’t provide one, it uses “today’s” date.)  Here’s screenshots of each:

datepicker   timepicker

OK, now to talk about the perplexing problems these controls presented me.  You’ll notice in the screenshots above, there’s an ApplicationBar.  And it has two icons (with no images).  After beating my head on my desk for a few minutes, I realized that these are the Done and Cancel buttons.  (You can also discover this by clicking on the ellipsis (…) icon.  They’ll slide up to reveal their text labels.

To make these icons actually work, you need to follow these instructions exactly:

  1. Create a folder in the root of your project named “Toolkit.Content”
  2. Add two images to that folder with the specific names:
    1. ApplicationBar.Cancel.png (download it here)
    2. ApplicationBar.Check.png (download it here)
  3. Make sure that the Build Action on those two images is set to “Content.”  If you haven’t done this before, just click on the images, and change it in the Properties tab.

properties

Once you’ve followed those specific instructions, IT JUST WORKS!  I wish this all just happened automatically, but at least we know.  And knowing is half the battle, right?

Here’s a look at the “working” ones:

datepickerfinal   timepickerfinal

GestureListener Control

Up until this point in the 31 Days of Windows Phone, you may have been wondering when you were going to find out how to handle gestures from your user in your application.  Today’s the day!  (DISCLAIMER: this is “one” way to do this.  There are plenty of other approaches to gesture handling, but this is definitely the easiest, and if you’ve been reading along, that’s what this series is optimized for.  The easiest way to accomplish something in Windows Phone.  Not necessarily the best practices that you should ALWAYS use.)

OK, now that that’s cleared up, let’s talk abut the GestureListener.  Much like the ContextMenu, we’re going to let the GestureService know that we’ve created a GestureListener, and then we basically rig up event handlers for the specific gestures we’re looking for.  Remember that we apply this to a specific XAML element, so the gestures will only be recognized on the control that this is applied to.  The gestures that are supported in the GestureListener are:

  • Tap
  • DoubleTap 
  • Hold
  • Flick
  • Pinch
  • Drag and Drop

Each of these are implemented in such a way, however, that it’s almost TOO easy to accomplish.  Pinch and Drag have a few more technical details (basically the delta between when the gesture started and when it completed.)  Here’s what our XAML would look like (on another rectangle):

<Rectangle Width="100" Height="100" Fill="Blue">
	<toolkit:GestureService.GestureListener>
		<toolkit:GestureListener 
			DoubleTap="DoubleTapped"
			Tap="Tapped"
			Hold="Held"
			DragStarted="DragStart"
				DragDelta="DragDelta"
				DragCompleted="DragEnd"
			Flick="Flicked"
			PinchStarted="PinchStart"
				PinchDelta="PinchDelta"
				PinchCompleted="PinchEnd" />
	</toolkit:GestureService.GestureListener>
</Rectangle>

As you can see, I can just define the gestures I want to recognize, and then assign event handlers to them, allowing me to translate that gesture to code very simply.  In the sample code for the Silverlight Toolkit for Windows Phone, there’s a great example of how to handle each of these events.

ToggleSwitch Control

You may have seen this control if you’ve tried to change the Date/Time in the Emulator.  Here’s a quick example:

dateandtime

Adding this to the page is simple:

<toolkit:ToggleSwitch Header="Receive updates automatically"/>

In the above screenshot, where it says “24-hour clock”, my example would read “Receive updates automatically.”  The On/Off text is automatically handled for you, thankfully.  If you’d like to do a little more customization to this control, however, it’s pretty easy to do.  There’s a HeaderTemplate and a ContentTemplate that we can leverage to make this control more “our own.”  There’s also Checked and Unchecked events that fire when the switch is manipulated.  (Think of this control much like you would a CheckBox).  Here’s an example of these being used (and bound to a data source):

<toolkit:ToggleSwitch Header="12:02 AM">
    <toolkit:ToggleSwitch.HeaderTemplate>
        <DataTemplate>
            <ContentControl FontSize="{StaticResource PhoneFontSizeLarge}" Foreground="{StaticResource PhoneForegroundBrush}" Content="{Binding}"/>
        </DataTemplate>
    </toolkit:ToggleSwitch.HeaderTemplate>
    <toolkit:ToggleSwitch.ContentTemplate>
        <DataTemplate>
            <StackPanel>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Alert: " FontSize="{StaticResource PhoneFontSizeSmall}"/>
                    <ContentControl HorizontalAlignment="Left" FontSize="{StaticResource PhoneFontSizeSmall}" Content="{Binding}"/>
                </StackPanel>
                <TextBlock Text="every weekday" FontSize="{StaticResource PhoneFontSizeSmall}" Foreground="{StaticResource PhoneSubtleBrush}"/>
            </StackPanel>
        </DataTemplate>
    </toolkit:ToggleSwitch.ContentTemplate>
</toolkit:ToggleSwitch>

Finally, we have the WrapPanel. While its purpose might seem obvious, it’s a control that is glaringly missing from the standard set of controls available in the original set.

WrapPanel Control

A WrapPanel is basically a StackPanel with some extra awesome sauce added.  I was building a game a few months ago, and I wanted to create a screen that had 30 buttons on it.  Since this was before the WrapPanel was available, I had to dynamically create a Grid, and then assign each new button to a Grid location.  Much more work than I wanted to do, just to get 30 buttons in a nice 5×6 layout.  The WrapPanel solves that problem for us.

In the example below, I have created a WrapPanel that contains 12 buttons. 

<toolkit:WrapPanel>
	<Button Width="75" Height="75" Content="1" />
	<Button Width="75" Height="75" Content="2" />
	<Button Width="75" Height="75" Content="3" />
	<Button Width="75" Height="75" Content="4" />
	<Button Width="75" Height="75" Content="5" />
	<Button Width="75" Height="75" Content="6" />
	<Button Width="75" Height="75" Content="7" />
	<Button Width="75" Height="75" Content="8" />
	<Button Width="75" Height="75" Content="9" />
	<Button Width="75" Height="75" Content="10" />
	<Button Width="75" Height="75" Content="11" />
	<Button Width="75" Height="75" Content="12" />
</toolkit:WrapPanel>

In the screenshot below, you’ll see that the WrapPanel dynamically decides how they will fit on each row, and stacks the next row below the first.  No overlap (much like a StackPanel), but also the freedom to not worry about the size of your content screwing up your layout.  Here’s a screenshot:

wrappanel

In my code example, below, you’ll see that I’ve rigged up events on Button #1 and Button #2.  They make the size of all of the buttons grow and shrink.  Playing with this example should demonstrate exactly how the WrapPanel dynamically moves your content around, even at runtime.  Here’s a screenshot of the same code, but with the buttons enlarged significantly:

wrappanelfinal

So that’s it!  We covered all 5 of the new controls available in the Silverlight Toolkit for Windows Phone.  Make sure you download it today, because I think you’ll find yourself needing these sooner than later.

Download the Code

In this sample code, you’ll find a simple example of each of the controls in the Silverlight Toolkit for Windows Phone.  On Day #31, we’ll be covering the Silverlight 3 Toolkit, and how we can leverage the charting controls in our WP7 applications.

download

31 Days of Windows Phone | Day #20: Map Control

This post is Day #20 in a series called the 31 Days of Windows Phone.

Yesterday’s mammoth post was on Push Notifications, and getting data to the phone, even when your app isn’t running.  Today, we’re back to controls, and more specifically, the Map Control.  As geolocation becomes more and more prevalent in mobile applications, it’s increasingly important to be able to show our user where they are, and what’s relevant near them.

Using the Map Control

Part of your Toolbox in Visual Studio 2010, you just need to drop a new Map Control on your page.  When you do, you’ll also notice that you need to add another XML namespace into your page.

xmlns:map="clr-namespace:Microsoft.Phone.Controls.Maps;assembly=Microsoft.Phone.Controls.Maps"

And here’s the default XAML that it used for my example (after I positioned it and sized it appropriately):

<map:Map Height="607" HorizontalAlignment="Left" Name="myMap" VerticalAlignment="Top" Width="456" />

Finally, a quick screen shot of the map in my application:

mapcontrolscreenshot

You’ll notice that in white text, it says “Invalid Credentials.  Sign up for a developer account.”  For the rest of this post, I am going to walk you through all of the different things we can do with this map control, including getting a valid developer API key.

Setting Up Your Developer Account

The first thing you should do, before building your mapping application, is to get a Bing Maps API key.  It’s a simple, free process, and it gets rid of that ugly white text from above.  To get one, head over to Bing Maps Portaland register.  Once you’ve done that, you need to create an API key.  Here’s what the form looks like:

createbingmapsapikey

When you fill this out, they will give you an API key that looks something like this:

AsWlUnHEvLgHlLHaRqTZLslewv1QIdGppxOqyL-7He2jxyHvLAjutrcntemUih-w9

(No, that’s not my API key.  I’ve changed many characters.  But it looks like what you should be looking for.)

 

 

Using the Credentials Provider

Now that you have an API key, we need to plug that in to our application.  If you’ve only got one map in your application, it’s perfectly fine to use it like this:

<map:Map CredentialsProvider="AsWlUnHEvLgHlLHaRqTZLslewv1QIdGppxOqyL-7He2jxyHvLAjutrcntemUih-w9">

If you’re going to be re-using this value over and over, you might want to save this value elsewhere, like your App.xaml file.  To do this, use the example below.  I’ve provided the code you’ll want to include in both your App.xaml file, as well as in your actual Map control.  We’re basically creating a static CredentialsProvider value in our App.xaml, and retrieving it on our page.

App.xaml

<Application.Resources>
	<map:ApplicationIdCredentialsProvider ApplicationId="AsWlUnHEvLgHlLHaRqTZLslewv1QIdGppxOqyL-7He2jxyHvLAjutrcntemUih-w9" x:Key="BingMapsAPIKey"></map:ApplicationIdCredentialsProvider>
</Application.Resources>

Map Control

<map:Map CredentialsProvider="{StaticResource BingMapsAPIKey}">

 

 

Changing the Map Control’s features

There are a whole host of options for changing the map’s look & feel.  For example, changing from Road to Aerial mode, or deciding whether to show the zoom level selector.  There is an incredible list of configurable options available to you, and they’re on the Bing Maps Silverlight Control Interactive SDK.  There’s no reason for me to cover ALL of the options outlined there (especially because they did an awesome job already), but because I’d rather focus on how you get your data on a map.  I’m going to focus on two things specifically:  adding a pushpin to a map, and adding custom shapes to a map.

Adding a Pushpin to the map

In C#, adding a pushpin to as simple as creating a new Pushpin object, setting its Location, and adding it to the map.  The same is true of doing it in XAML.  Obviously, XAML provides you some shortcuts, but neither example is very difficult.

XAML

<map:Pushpin Location="40.1449, -82.9754" FontSize="30" Background="Orange" Content="1" />

C#

Pushpin pushpin = new Pushpin();
Location location = new Location();
location.Latitude = 40.1449;
location.Longitude = -82.9754;
pushpin.Location = location;
pushpin.Background = new SolidColorBrush(Colors.Orange);
pushpin.Content = "1";
pushpin.FontSize = 30;
MapControl.Children.Add(pushpin);

The above example, in either case, will add a pushpin to my office, found at 8800 Lyra Drive, Columbus, OH.  Here’s what it looks like in my application:

pushpin

If you’re wondering how you can convert your address data to latitude/longitude, check out my post from the 31 Days of Silverlight.  It specifically covers Geocoding addresses, and is still exactly what you’re going to want to do in your phone application.

Adding Custom XAML to a map

Another little control we have in the Map assembly is the MapPolygon.  By supplying it with a list of Locations, it will draw a custom polygon shape on your Map, which stays in place even as the user scrolls and pans around the map.  It is tied to specific longitude and latitude values, making it very easy to delineate countries, states, regions, or even parking lots, if that’s what your app is for.  Here’s how to do it:

XAML

<map:MapPolygon Fill="Purple" Stroke="White" Opacity=".7" Locations="40.1449,-82.9754 40.1449,-12.9754 10.1449,-82.9754" />

C#

MapPolygon mapPolygon = new MapPolygon();
mapPolygon.Fill = new SolidColorBrush(Colors.Purple);
mapPolygon.Stroke = new SolidColorBrush(Colors.White);
mapPolygon.Opacity = .7;
LocationCollection locations = new LocationCollection();
Location location = new Location();
location.Latitude = 40.1449;
location.Longitude = -82.9754;
Location location1 = new Location();
location1.Latitude = 40.1449;
location1.Longitude = -12.9754;
Location location2 = new Location();
location1.Latitude = 10.1449;
location1.Longitude = -82.9754;
locations.Add(location);
locations.Add(location1);
locations.Add(location2);
mapPolygon.Locations = locations;

MapControl.Children.Add(mapPolygon);

So there you have it.  We’ve now added a Pushpin and a custom polygon overlay to our map.  Make sure to check the Bing Maps Silverlight Control Interactive SDKfor tons more you can do with this awesome control.  (Screenshot of the MapPolygon is below.)

mappolygon

Download the Code

In this sample code, you’ll find examples for adding a pushpin as well as a polygonal shape to your map in both XAML and C#.  You don’t need both, so pick one or the other, depending on your needs.

download

31 Days of Windows Phone | Day #19: Push Notifications

This post is Day #19 in a series called the 31 Days of Windows Phone.

Yesterday, I wrote about the WebBrowser control, and how to leverage it in your applications.  Today, we’re going to talk about, quite possibly, the most important topic in this series: Push Notifications.

If you’re not familiar with the concept of Push Notifications, it’s pretty simple: instead of forcing your application to check the server for new data every few minutes, your server has the ability to tell your phone when there’s new data.

Why Use Push Notifications?

For one, you’ll save your user’s battery.  Calling back to a server to check for data takes power, and on a phone, power is an absolute scarcity.  You’ll never have enough, and no matter how long your battery lasts, avoiding push notifications will only make that time shorter.

Secondly, you can leverage push notifications to let your user know that something interesting is happening with your application, even if it’s not running.  You can alert the user that they should open your application to interact with whatever it is you needed to tell them.

The Push Notification Process

So that you understand all of the code I’m about to throw at you, I thought it might be a good idea to explain exactly what is happening in this process.

  1. The first time a user runs your application on their phone, the app will call out to Microsoft’s Push Notification service, requesting a custom URI for communications purposes.
  2. When an event happens on your web service, you should pass messages to that URI (with a specific payload), and the Push Notification services will deliver that data to your user’s phone, in the form of a Live Tile update, a Toast notification, or as actual data to your application.

This article is going to focus on the “how” of each of the above bullet points.  If you want to see an example that you can build step-by-step, check out the Windows Phone Developer Training Kit.  It’s got an outstanding Push Notification tutorial that you can use.

Retrieving a Custom URI from the Push Notification Service

Thankfully, they’ve made this part incredibly simple.  We need to use the Microsoft.Phone.Notification assembly, but otherwise, we can get a custom URI from the Push Notification service (PNS) in about 10 lines of code.  First, we’ll create a new HttpNotificationChannel.  This will automatically communicate with the PNS (on a seperate thread), and we’ll create an event to capture what the service returns.

HttpNotificationChannel channel;

void GetPushChannel()
{
	channel = new HttpNotificationChannel("BLANKENSOFT_" + DateTime.Now.Ticks.ToString());
	channel.ChannelUriUpdated += new EventHandler<NotificationChannelUriEventArgs>(channel_ChannelUriUpdated);
	channel.Open();
}

void channel_ChannelUriUpdated(object sender, NotificationChannelUriEventArgs e)
{
	Dispatcher.BeginInvoke(delegate
	{
		URIBlock.Text = channel.ChannelUri.ToString();
	});
}

The custom URI I received from this example was (it’s small so it fits):

http://sn1.notify.live.net/throttledthirdparty/01.00/AAHsLicyiJgtTaiDbJoSgmFiAgAAAAADAwAAAAQUZm52OjlzOEQ2NDJDRkl5MEVFMEQ

Once you have the URI, you’ll want to save that to your web service.  It’s your web service that will be initiating the messages to the phone, and we can do that one of three ways: Tile notification, Toast notification, or a Raw notification.  We’ll cover each of these in the next section.

Different Messages For Different Needs

Earlier I mentioned that there are three different types of messages you can send to a phone.  Here’s a quick outline of what those are:

Raw Notification – Raw notifications are used when your application is actually running on the device.  This allows you to update your interface “live” as the user is using it.

Toast Notification – This message will be received regardless of whether your application is running or not, but popping toast messages while your app is running might be a little annoying.  I’ll demonstrate this example below.  Toast WILL NOT also update your application’s data.  You still need to pass a Raw Notification to make this happen.

Tile Notification – If your application is pinned to the user’s Start screen, you can update the Tile for your application.  You can change the background image, as well as an integer from 0-99.

Sending a Toast Notification

Once we’ve got our Push URI, it’s just a matter of composing an HTTP message, and sending it to that URI.  Here’s an example in code:

HttpWebRequest sendNotificationRequest = (HttpWebRequest)WebRequest.Create(channel.ChannelUri.ToString());
sendNotificationRequest.Method = "POST";
//Indicate that you'll send toast notifications!
sendNotificationRequest.ContentType = "text/xml";
sendNotificationRequest.Headers = new WebHeaderCollection();
sendNotificationRequest.Headers.Add("X-NotificationClass", "2");
if (string.IsNullOrEmpty(txtMessage.Text)) return;
		
//Create xml envelope
string data = "X-WindowsPhone-Target: toastrnrn" +
		"<?xml version='1.0' encoding='utf-8'?>" + 
		"<wp:Notification xmlns:wp='WPNotification'>" + 
		"<wp:Toast>" + 
		"<wp:Text1>{0}</wp:Text1>" +
		"</wp:Toast>" + 
		"</wp:Notification>"; 
		
//Wrap custom data into envelope
string message = string.Format(data, txtMessage.Text);
byte[] notificationMessage = Encoding.Default.GetBytes(message);
		
// Set Content Length
sendNotificationRequest.ContentLength = notificationMessage.Length;
		
//Push data to stream
using (Stream requestStream = sendNotificationRequest.GetRequestStream())
{
	requestStream.Write(notificationMessage, 0, notificationMessage.Length);
}
	
//Get reponse for message sending
HttpWebResponse response = (HttpWebResponse)sendNotificationRequest.GetResponse();
string notificationStatus = response.Headers["X-NotificationStatus"];
string notificationChannelStatus = response.Headers["X-SubscriptionStatus"];
string deviceConnectionStatus = response.Headers["X-DeviceConnectionStatus"];

As you can see, the code for this portion can get long and convoluted quickly.  My recommendation is to spend some time going through the Windows Phone Developer Training Kit, and specifically walking through the Push Notification example.

It’s an outstanding example of how push notifications work (from front to back), and shows you just how powerful these updates can be to keep your application in front of your user’s eyes.

Download The Code

For today’s example, downloading the above code won’t do you much good without all of the context that it requires.  Today’s download is actually the final example from the Push Notification demo in the Windows Phone Developer Training Kit.  Enjoy!

download

31 Days of Windows Phone | Day #18: WebBrowser Control

This post is Day #18 in a series called the 31 Days of Windows Phone.

For the past two days, we have been talking about different display controls: Panorama and Pivot.  Today, we’re going to focus on another important control, the WebBrowser.

What does the WebBrowser control do?

If it’s not obvious, the WebBrowser control lets your user browse a specific web page.  But it’s not a full browser, because it doesn’t come with an address bar, favorites, tabs, etc.  It’s probably best think of it as an <iframe> from the HTML world, but with a much richer interface.  You’ll discover that pinch (and double-tap) to zoom, as well as panning and scrolling are automatically built in, without any work on your part.

One other awesome feature of this control is that it can load both local and web content.  This means that if I’ve got a ton of HTML assets (documentation, maybe?), I don’t have to re-create all of that content again for my application.  Instead, I can embed those HTML pages in my application, and load them locally on the phone rather than relying on a potentially spotty data connection.

Loading local HTML content in the WebBrowser control

Since I brought it up, I should probably show you how to so it too, right?  First, you need some local HTML files added to your project.  I have added two for demonstration purposes, but this could be hundreds if you needed that.

addhtmlfiles

After that, I rigged up two buttons to load these individual files.  Again, there are many different approaches you can take to this, but I want to make sure that you walk away from this article confident you can load local content, and I’ll leave it to you to find the best way to leverage my examples.  In my code below, there are two additional references (“using statements”) you’ll need to make.  They are:

using System.IO;
using Microsoft.Xna.Framework;

You may be thinking, “XNA?  Really?”  I’m here to tell you that on Day #30 of this series, I’m going to show you just how powerful the XNA namespaces can truly be.  For now, just trust me.  In my button event handlers, I have two lines of code.  The first loads the contents of the HTML into a StreamReader, and the second line loads the contents of the HTML file into the WebBrowser control using its .NavigateToString() method.  Here’s what it looks like:

StreamReader reader = new StreamReader(TitleContainer.OpenStream("html/wp7wiki.html"));
Browser.NavigateToString(reader.ReadToEnd());

If you’d like to read up on the System.Xna.Framework, or the TitleContainer class, click on their respective links in this sentence.  Using this simple example above, however, will allow you to load local HTML content directly into your WebBrowser control.

Scripting is disabled by default

In case you’re planning on loading an HTML page that contains some JavaScript, you should know that scripting is disabled in the WebBrowser control by default.  It’s simple to turn back on (or even toggle) using the IsScriptEnabled property of the control.  Here’s two quick examples:

XAML

<phone:WebBrowser x:Name="Browser" IsScriptEnabled="True" />

C#

Browser.IsScriptEnabled = true;

Talking Between Your App and Script

If you want to be able to leverage the scripting that you have on your HTML content, it’s pretty easy to do.  If you want to pass data from your app to the page, you can simply use the .InvokeScript() method, passing the name of the script method, followed by any arguments the method expects:

string returnValue = (string)Browser.InvokeScript("getText", "http://jeffblankenburg.com", "rocks", "awesomely");

To do the opposite, you need one extra step: an event handler for when the a script wants to talk to you.  To do this, I set up the .ScriptNotify event handler, and grab the string it passes to me (in my case, it’s a URL that I will navigate to).  The NotifyEventArgs.Value contains the value the script passes me:

void Browser_ScriptNotify(object sender, NotifyEventArgs e)
{
	Browser.Navigate(new Uri(e.Value, UriKind.Absolute));
}

Once you’ve got that set up, it’s one simple line of Javascript to make that event fire:

window.external.Notify("http://jeffblankenburg.com");

Because you’re loading network content most of the time, you need to let your user that something is happening.  This seems like a perfect opportunity to talk about the ProgressBar, and how we can use it to show the user that we’re loading something, and that they should be patient.

Using the ProgressBar with the WebBrowser control

There is TONS of information about the ProgressBar at MSDN, so I’m not going to cover all of it.  What I will do, however, is show you how to create a simple “waiting” animation for your user, so that they know you’re loading content.  By using the ProgressBar in the example below, we just need to set IsIndeterminate = true, and show and hide it at the appropriate times.  Here’s the XAML and C# I use to do this:

XAML

<ProgressBar Foreground="Orange" x:Name="ProgBar" Visibility="Collapsed" IsIndeterminate="True" Height="4" HorizontalAlignment="Left" Margin="10,66,0,0" VerticalAlignment="Top" Width="460" />

C#

void Browser_Navigating(object sender, NavigatingEventArgs e)
{
	ProgBar.Visibility = Visibility.Visible;
}

void Browser_Navigated(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
	ProgBar.Visibility = Visibility.Collapsed;
}

You’ll see that I can use the Navigated and Navigating event handlers to show the ProgressBar to the user at the appropriate times, and hide it otherwise.  Check out the code sample below to see all of this in action!

Download the Code

Today we covered the WebBrowser control in depth, but as with all of my examples, until you can take some working code apart, and see how it works, it’s hard to fully realize what you’re working with.  So do it!  Download this example, and figure out how to add it to your project.

download

31 Days of Windows Phone | Day #17: The Pivot Control

This post is Day #17 in a series called the 31 Days of Windows Phone.

Yesterday, we talked about the Panorama control, how to use it, and what it’s purpose is.  Today, I’m going to cover a similar, but different control called the Pivot.

What is a Pivot Control?

I view Pivot controls as a great control for giving your user different “slices” of the same data.  For example, in the Calendar on Windows Phone, you can flip between the “agenda” and “day” views.  They present the same data, but in two completely different views.  Another great way to use the Pivot control is to use it to categorize items into different buckets.  The Settings are a great example of that on the phone as well. You have settings for the system, and settings for specific applications. Here’s a quick glance at those examples:

calendar   systemsettingsscreenshot

Are there specific times I should use Panorama vs. Pivot controls?

Yes, there absolutely are.  And there are two great places you can read/watch more about this.  Tim Heuer wrote a great article specifically about when you should use each control, and there’s also a great video on Channel 9 from the Windows Phone Design Days Series.

My guidelines are pretty simple:

  • Use a Panorama as an introduction to everything that is interesting about your application.
  • Use a Pivot when you want to show the same data in different ways to your user.

Using The Pivot Control

If you didn’t read yesterday’s post on the Panorama control, check it out.  I walk you through exactly how to get the Panorama and Pivot controls into Visual Studio 2010’s Toolbox.  For now, we’re going to dive directly into the structure of a Pivot control, and how to use it.

The structure is very similar to the Panorama, but in today’s example, instead of static content, I’m also going to bind a list of data to our ListBox control, using DataTemplates to do it.  Here’s my base Pivot control before I add any content to it (this sample application displays lists of baby names, based on gender):

<controls:Pivot Title="BABY NAMES">
	<controls:PivotItem Header="boys">
			
	</controls:PivotItem>
	<controls:PivotItem Header="girls">
			
	</controls:PivotItem>
	<controls:PivotItem Header="either">
			
	</controls:PivotItem>
</controls:Pivot>

Obviously, this doesn’t get us much without some data.  Let’s do that next,

Using ListBoxes with DataTemplates

For each of my PivotItems, I am going to add a ListBox control, and inside it, I’m going to define an ItemTemplate that defines what each data entry should look like.  Here’s the XAML I’ve added:

<controls:Pivot Title="BABY NAMES">
	<controls:PivotItem Header="boys">
		<ListBox x:Name="boyList" Margin="0,0,-12,0">
			<ListBox.ItemTemplate>
				<DataTemplate>
					<StackPanel Margin="0,0,0,17" >
						<TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
					</StackPanel>
				</DataTemplate>
			</ListBox.ItemTemplate>
		</ListBox>
	</controls:PivotItem>
	<controls:PivotItem Header="girls">
		<ListBox x:Name="girlList" Margin="0,0,-12,0">
			<ListBox.ItemTemplate>
				<DataTemplate>
					<StackPanel Margin="0,0,0,17" >
						<TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
					</StackPanel>
				</DataTemplate>
			</ListBox.ItemTemplate>
		</ListBox>
	</controls:PivotItem>
	<controls:PivotItem Header="either">
		<ListBox x:Name="allList" Margin="0,0,-12,0">
			<ListBox.ItemTemplate>
				<DataTemplate>
					<StackPanel Margin="0,0,0,17" >
						<TextBlock Text="{Binding Name}" TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
					</StackPanel>
				</DataTemplate>
			</ListBox.ItemTemplate>
		</ListBox>
	</controls:PivotItem>
</controls:Pivot>

One thing we haven’t talked about much in this series is DataBinding.  You’ll notice that for each TextBlock, the Text value is defined as “{Binding Name}.”  What this means is that for whatever object I pass into this ListBox, the TextBlock will use the object’s Name property to populate it’s Text value.  To get this data into the ListBox, we have to write a little code in our code-behind file (this is the entire contents of MainPage.xaml.cs):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;

namespace Day17_PivotControl
{
	public partial class MainPage : PhoneApplicationPage
	{
		BabyName[] names = new BabyName[10] {new BabyName("Steve", 1, 0),
					new BabyName("Jennifer", 2, 0),
					new BabyName("Alex", 1, 2),
					new BabyName("Casey", 1, 2),
					new BabyName("Quinn", 1, 2),
					new BabyName("Anthony", 1, 0),
					new BabyName("Sarah", 2, 0),
					new BabyName("Parker", 2, 1),
					new BabyName("Jessica", 2, 0),
					new BabyName("Jeff", 1, 0)};
		
		// Constructor
		public MainPage()
		{
			InitializeComponent();
			boyList.ItemsSource = from n in names
					where (n.Gender1 == 1 || n.Gender2 == 1)
					orderby n.Name
					select new BabyName(n.Name, n.Gender1, n.Gender2);

			girlList.ItemsSource = from n in names
					where (n.Gender1 == 2 || n.Gender2 == 2)
					orderby n.Name
					select new BabyName(n.Name, n.Gender1, n.Gender2);

			allList.ItemsSource = from n in names
					orderby n.Name
					select new BabyName(n.Name, n.Gender1, n.Gender2);
		}
	}
}

You’ll see that for each ListBox, I’m defining the .ItemsSource using some simple LINQ syntax against my array of BabyName objects.  If you’re not familiar with LINQ, you’ve been missing out on Language Intergrated Query.  There’s a great list of resources on LINQ here.

By defining these queries, I’m able to simply sort and parse my collection of data, and assign different collections of the same data to each of the PivotItem sections.

So that’s about it!  You shouldn’t generally use more than 7 sections in a Panorama or Pivot control (if you are, you might want to think about doing it differently…), primarily because that’s the most that your users will be able to remember.  If they don’t remember it’s there, it’s unlikely they’ll use it, right?  (7 has been a well-known memory limit for humans, which is why phone numbers are the same length.)

Download the Code

This was a simple example of how to implement a Pivot control in Windows Phone 7, using actual data to populate ListBoxes.  Please download it and learn by playing with it.

download

31 Days of Windows Phone | Day #16: The Panorama Control

This post is Day #16 in a series called the 31 Days of Windows Phone.

Yesterday, we talked about Isolated Storage, and how we can persist data on the device for our applications.  Today, I’m going to completely switch gears, and visit a relatively new (but awesomely powerful) control available to us: the Panorama control.

What is a Panorama Control?

If you’ve seen videos or screenshots of the “hubs” in Windows Phone 7, Panorama controls are used extensively there.  In short, they are that multi-screen scrolling menu of options, navigation, and data. Here’s a couple of examples:

 peoplehub

 xboxlivehub

OK, now that we know what a Panorama control looks like, let’s talk about implementing one.

Creating a Panorama Project

For the first 15 days of this series, every project has been based on the default Windows Phone Application template.  For a Panorama, you can use the Windows Phone Panorama Application, if you’d like.  Here it is in the list:

 panoramaproject

The important thing to note, however, is that you don’t HAVE to use this template to have a Panorama.    This project template leverages an MVVM framework for its data (a great approach, by the way), and predefines a bunch of stuff for you.  Put simply, the Panorama control is just another control at our disposal, and we can add it to any page that we’d like.  That’s what I’m going to show you in this article.

Adding a Panorama To Your Toolbox

The first thing to know about adding a Panorama to your page is that it’s not one of the default controls that is always available to you (which is why it doesn’t show up in your Toolbox in Visual Studio 2010).  You have to specifically add its namespace to your page before you can use it.  The easy way to do this is to add it to your Toolbox, and then re-use it from there.

The first thing you’re going to want to do is open your Toolbox, and right click on the “Windows Phone controls” tab.  Select “Choose Items…” from the list.

 chooseitems

In the dialog box that appears, it automatically loads with the Windows Phone Components tab open for you.  You’ll see that several of the controls are already checked.  Those are the ones currently in your Toolbox.  Scroll down until you find the Panorama, and add it.  (We’re covering the Pivot control tomorrow, so you may as well add that one now, too.)

 choosetoolboxitems

Once you’ve added those to your Toolbox, you’ve got a very easy way to add a Panorama control to your pages.

Adding a Panorama To Your Page

We took those previous steps to make your life easier.  Delete all of the XAML elements from your page, and then add your Panorama.  By dragging a Panorama from your Toolbox, you’re all set.  The default syntax looks like this:

<controls:Panorama />

Not much to start with, huh?  You should also note, however, that a new XML namespace was also added to your page:

xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"

Now that we’ve got the absolute MINIMUM amount of code on our page, let’s make this Panorama control actually look and feel like one.  Here’s an illustration of what the different pieces of the Panorama control look like:

pictureshub

Setting the Panorama Background and Title

One of the cool features of the Panorama control is the ability to have one large image in the background, that scrolls slower than the rest of the content.  Find a cool, representative image to use for your application.  Here’s mine (my application is for filling the time you have to wait for your food in a restaurant.  This is the Corner Grill in Bowling Green, OH.):

 PanoramaBackground

To apply this as the background of my Panorama control, I just need to add the image to my project, and create an ImageBrush with the photo as the source.  You’ll notice that I’ve also set the Opacity of the image to 50%.  This is because white text won’t show up on this light image very well.

<controls:Panorama Title="waiter">
	<controls:Panorama.Background>
		<ImageBrush ImageSource="PanoramaBackground.jpg" Opacity=".5" />
	</controls:Panorama.Background>
</controls:Panorama>

Here’s what it looks like on the phone:

 backgroundscreenshot

OK, we’ve got a background image. Now let’s start adding some content to it.

Creating a PanoramaItem (sections of the Panorama)

Right now, our application doesn’t work very well.  It just shows our background image.  It doesn’t scroll, or show anything at all.  By adding PanoramaItems, we are creating the individual sections of the Panorama control, and within those PanoramaItems, we can add the XAML that will show up in those sections.

Each PanoramaItem is completely independent of another, so you can technically make each section look completely different.  I’ll walk you through the code for a PanoramaItem, and then we can talk about the custom content in the next section.  You’ll notice below that I have defined three PanoramaItems, and given each one of them a header.  This is probably better illustrated with screenshots, so I’ll include those after the code.

<controls:Panorama Title="waiter">
	<controls:Panorama.Background>
		<ImageBrush ImageSource="PanoramaBackground.jpg" Opacity=".5" />
	</controls:Panorama.Background>
	<controls:PanoramaItem Header="learn">
		
	</controls:PanoramaItem>
	<controls:PanoramaItem Header="play">
		
	</controls:PanoramaItem>
	<controls:PanoramaItem Header="all">
		
	</controls:PanoramaItem>
</controls:Panorama>

1stpanel   2ndpanel   3rdpanel

Notice how the Background scrolls, as well as the title, but that they’re not really at the same speed?  This gives the application a significant amount of visual depth as the user pans through it.  But it’s still pretty empty.  Let’s get some content in there, so that it looks more like this:

 allshot

Adding Content to a PanoramaItem

You certainly don’t HAVE to, but I’d always recommend starting with a ListBox.  This gives you the power to scroll your content vertically, if you have too much.  You have many, many options when it comes to layout, but a ListBox is probably going to offer you the most convenience.  (Plus, binding a list of items in code to it is WAY simple.  Check out this tutorial from Scott Guthrie.)

For my example, I have 5 applications that I want you to be able to launch from this screen.  I’ve created some custom XAML for this, and placed it inside my ListBox.  Here’s what the XAML looks like, and a screenshot of the “Play” section in the emulator:

<controls:PanoramaItem Header="play">
	<ListBox Margin="0,0,-12,0">
		<StackPanel Orientation="Horizontal" Margin="0,0,0,17">
			<Image Height="100" Width="100" Source="icons/tictactoe.png" Margin="12,0,9,0"/>
			<StackPanel Width="311">                                    
				<TextBlock Text="tic tac toe"  TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
				<TextBlock Text="the classic two player game" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
			</StackPanel>
		</StackPanel>
		<StackPanel Orientation="Horizontal" Margin="0,0,0,17">
			<Image Height="100" Width="100" Source="icons/numbers.png" Margin="12,0,9,0"/>
			<StackPanel Width="311">
				<TextBlock Text="numbers"  TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
				<TextBlock Text="learn your digits from 1 - 20" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
			</StackPanel>
		</StackPanel>
		<StackPanel Orientation="Horizontal" Margin="0,0,0,17">
			<Image Height="100" Width="100" Source="icons/wordsearch.png" Margin="12,0,9,0"/>
			<StackPanel Width="311">
				<TextBlock Text="word search"  TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
				<TextBlock Text="find as many words as you can" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
			</StackPanel>
		</StackPanel>
		<StackPanel Orientation="Horizontal" Margin="0,0,0,17">
			<Image Height="100" Width="100" Source="icons/animals.png" Margin="12,0,9,0"/>
			<StackPanel Width="311">
				<TextBlock Text="animals"  TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
				<TextBlock Text="hear and learn your favorites" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
			</StackPanel>
		</StackPanel>
		<StackPanel Orientation="Horizontal" Margin="0,0,0,17">
			<Image Height="100" Width="100" Source="icons/alphabet.png" Margin="12,0,9,0"/>
			<StackPanel Width="311">
				<TextBlock Text="alphabet"  TextWrapping="Wrap" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
				<TextBlock Text="learn your letters" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
			</StackPanel>
		</StackPanel>
	</ListBox>
</controls:PanoramaItem>

 playshot

So that’s about it!  I have each of the icons link to their own individual XAML file, but this Panorama provides my user the ability to navigate through my application before actually playing any of the individual games.

Download the Code

This sample code includes everything we covered in this article.  Download it and learn the Panorama control for yourself!

download

31 Days of Windows Phone | Day #15: Isolated Storage

This post is Day #15 in a series called the 31 Days of Windows Phone.

Yesterday, we talked about tombstoning our applications, so that they appear to be running in the background.  Today, I’m going to cover a great way to store your data locally on the phone, using Isolated Storage.

What Is Isolated Storage?

Isolated Storage is not a new concept.  It’s been used in Silverlight since version 2.  It’s basically a way to store data or files on the local file system.  It’s “isolated” because only your application has access to the data.  If you have two applications, and you want to share data between them, you’d better have some kind of cloud-based service that can share that data for you.  Applications will not have the ability to share, call, or interact with other applications on the device.

Settings vs. Files

There are two ways to store your data locally.  The first is through a library of name/value pairs.  This is called IsolatedStorageSettings.  The second way is through actual file and folder creation.  This is called IsolatedStorageFile.  The image below (courtesy of MSDN) helps illustrate this briefly, and then I will dive into examples of each.

isolatedstorage

IsolatedStorageSettings

For many purposes, this might be the only storage that you need.  IsolatedStorageSettings allows you to store name/value pairs in a dictionary (without ANY setup, mind you), that you can retrieve later.  This data is persisted across application stop/start, powering the phone off, etc.  It’s there until you remove it, or the user uninstalls your application.  One important thing to remember is that you can’t retrieve a value until it’s been added to the library.  In each of my examples, you’re going to see code that checks to see if the value exists first, before retrieving it.  Here’s an example of the code you’d need to save a user’s preference for receiving email updates from your application.  I have one CheckBox that allows a user to decide, and events that store that value to IsolatedStorage.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.IO.IsolatedStorage;

namespace Day15_IsolatedStorage
{
	public partial class MainPage : PhoneApplicationPage
	{
		IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
		
		// Constructor
		public MainPage()
		{
			InitializeComponent();
			InitializeSettings();
		}

		private void InitializeSettings()
		{
			if (settings.Contains("emailFlag"))
			{
				EmailFlag.IsChecked = (bool)settings["emailFlag"];
			}
			else settings.Add("emailFlag", false);
		}

		private void EmailFlag_Unchecked(object sender, RoutedEventArgs e)
		{
			settings["emailFlag"] = false;
		}

		private void EmailFlag_Checked(object sender, RoutedEventArgs e)
		{
			settings["emailFlag"] = true;
		}
	}
}

As you can see, this is incredibly simple.  Here’s a few things to remember:

  1. Trying to retrieve a value from IsolatedStorageSettings will throw an error if it hasn’t already been created.  Make sure you initialize your settings, or ALWAYS check the .Contains property first.
  2. You can save anything you want in the Settings.  I saved a boolean value in my example, but you could also save a Customer object, or any other else you can come up with.
  3. Remember that you have to explicitly cast your data when you retrieve it.  You’ll notice that I have to cast my bool value before I can use it.  You’re saving the object, but the storage does NOT save the type.  That’s up to you when you want to use it again.
  4. Setting a value is the same as adding a value to the library.  The “settings.Add()” statement is actually unnecessary, but I added it so that you could see the syntax.

So that’s about it.  IsolatedStorageSettings is pretty straightforward.  Save name/value pairs with very little actual code.  Creating and saving files is a little more complicated, but still surprisingly simple.  Let’s take a look at that now.

IsolatedStorageFile

Using IsolatedStorageFile is the mechanism you can use for storing actual FILES on the user’s device.  In my example, I’m going to create a text file in a subdirectory, and then retrieve the contents of that file.  We have the ability to create and delete folders, subfolders, and files.  This is going to seem like a TON more code, but it’s actually pretty simple.  We’re creating a new IsolatedStorageFile object, and then writing it to the drive using an IsolatedStorageFileStream.  I’ve added comments to my code inline, so that you can see what is happening a little easier.  I have two events, one that saves the file, and one that reads it:

using System.IO.IsolatedStorage;
using System.IO;

private void SaveButton_Click(object sender, RoutedEventArgs e)
{
	//Obtain a virtual store for application
	IsolatedStorageFile fileStorage = IsolatedStorageFile.GetUserStoreForApplication();

	//Create new subdirectory
	fileStorage.CreateDirectory("textFiles");

	//Create a new StreamWriter, to write the file to the specified location.
	StreamWriter fileWriter = new StreamWriter(new IsolatedStorageFileStream("textFiles\newText.txt", FileMode.OpenOrCreate, fileStorage));
	//Write the contents of our TextBox to the file.
	fileWriter.WriteLine(writeText.Text);
	//Close the StreamWriter.
	fileWriter.Close();
}

private void GetButton_Click(object sender, RoutedEventArgs e)
{
	//Obtain a virtual store for application
	IsolatedStorageFile fileStorage = IsolatedStorageFile.GetUserStoreForApplication();
	//Create a new StreamReader
	StreamReader fileReader = null;

	try
	{
		//Read the file from the specified location.
		fileReader = new StreamReader(new IsolatedStorageFileStream("textFiles\newText.txt", FileMode.Open, fileStorage));
		//Read the contents of the file (the only line we created).
		string textFile = fileReader.ReadLine();

		//Write the contents of the file to the TextBlock on the page.
		viewText.Text = textFile;
		fileReader.Close();
	}
	catch
	{
		//If they click the view button first, we need to handle the fact that the file hasn't been created yet.
		viewText.Text = "Need to create directory and the file first.";
	}
}

This doesn’t seem like much of an amazing trick until you leave the application, come back, and try to load the file again (and it’s still there!).

So there you have it.  We have two simple storage mechanisms available to us in Windows Phone 7.  IsolatedStorageSettings and IsolatedStorageFile.  I’d be interested to hear the creative ways you are leveraging these storage structures in your application.  Please leave comments!

Download the Code

This example code incorporates both the Settings and File storage code shown above in one project.

download

31 Days of Windows Phone | Day #14: Tombstoning (Multi-tasking)

This post is Day #14 in a series called the 31 Days of Windows Phone.

Yesterday, we talked about using Location data to give our applications a more custom, in-the-know kind of feel.  Today, I’m writing on perhaps the most controversial topic available for Windows Phone 7: multitasking.

There’s been plenty of articles written about where Windows Phone 7 will struggle, and #1 at the top of that list is always “Lacks multi-tasking.”

Windows Phone 7 Does Multitasking

Yes.  I said it.  And I said it because it’s true.  A Windows Phone is absolutely a multi-tasking device.  I can listen to music while playing a game, or receive email while I’m surfing the web.  Where the misinformation appears is when we, as developers of apps for the platform, discover that we can’t build apps that run in the background.

In the many months that I have been working with Windows Phone 7, I have only been able to come up with two really compelling reasons to need my application to run in the background on my phone.

  1. My app plays music.  Like Pandora.  I will completely concede that this needs to be able to be done in the background.  The user will definitely notice if the music stops playing.
  2. My app needs data from the device’s sensors.  Like GPS.  If my app’s not running, I can’t tell you that you’ve run the 4 miles you wanted to run.

Outside of those two examples, however, I haven’t been presented with another situation in which having my app run in the background is necessary.  (For those of you writing apps that DO fall into one of those categories, you can appeal to the “powers that be” for access to a “super API” that DOES allow background processing.  I’ll warn you now though…you’re going to have to have a pretty compelling reason to get access to that.)

Before you say “but what about receiving updates from my web service?  Don’t I need to be running to get those?” my answer is NO, no you don’t.  There’s a great mechanism called Push Notification services that I will cover on Day #19 that solves this problem in a very elegant way.

For the rest of us, they’ve given us a great mechanism called “tombstoning” that allows us to pretend as if our application was always running, even though our process was killed.  Here’s a quick diagram of how it works:

tombstoninglifecycle

As you can see from the illustration above, there are deactivation and reactivation events that we can leverage when a user enters and exits our application.  By using these events, we can make it appear to our user as if our application never stopped running.  When we add in Isolated Storage (Day #15), and Push Notifications (Day #19), this becomes an incredibly powerful story.

Pretending to Multitask

There are four built-in methods in your App.xaml.cs file (for more information about the structure of your project files, check out Day #1).  Here’s a quick look at their default state, with the default comments inline.

// Code to execute when the application is launching (eg, from Start)
// This code will not execute when the application is reactivated
private void Application_Launching(object sender, LaunchingEventArgs e)
{
}

// Code to execute when the application is activated (brought to foreground)
// This code will not execute when the application is first launched
private void Application_Activated(object sender, ActivatedEventArgs e)
{
}

// Code to execute when the application is deactivated (sent to background)
// This code will not execute when the application is closing
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
}

// Code to execute when the application is closing (eg, user hit Back)
// This code will not execute when the application is deactivated
private void Application_Closing(object sender, ClosingEventArgs e)
{
}

The “Launching” and “Closing” methods can be used in the traditional cases: starting and exiting the app through traditional methods (leaving with Back button, for example, or starting the app from the App List).  The Activated and Deactivated methods are for those non-traditional entrances and exits.  For example, using the Back button to go back to our application.  Or leaving our app because the user answered a phone call.  Those are non-traditional.  I recommend testing these cases heavily, but those should be solid guidelines to start with.

You are supposed to use these methods to save your state when a user exits your application, and then refresh that state when they return, thus creating the illusion that they never left.  The reason that we do this is pretty simple:

  1. Most users don’t realize that when they leave an application, it’s still eating system resources and battery life in the background. (If you’re reading this article, you’re NOT most users.)
  2. Most applications don’t NEED to run in the background.  There are better ways to use the device’s resources.

Saving Your State on Deactivation

The first thing we’re going to want to do when the user exits is save their information.  In my example application, we’re going to build a timer that appears to be running, even when it isn’t.  If you want to see all of the code, flip down to the bottom of this article, and look for the “Download the Code” section.  I’m only going to show the portions of the code relevant to tombstoning, but the entire application is available down there for you to play with.

To save data, I’m going to use the PhoneApplicationService.  I’m going to cover Isolated Storage tomorrow (Day #15), a more persistent way to save your data.  In my example, I want to know what time you exited my application, so that I can figure out the difference between when you exited and when you arrive the next time.

private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
	PhoneApplicationService.Current.State["LeftTime"] = DateTime.Now;
}

In my application, I also have an OnNavigatedTo event that fires when I load that page.  If my “LeftTime” value exists, then I use that, otherwise, I assume you are starting the application for the first time.

Restoring Your State on Reactivation

In this example, I restore my values from the ones that I saved when I exited.

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
	base.OnNavigatedTo(e);
	if (PhoneApplicationService.Current.State.ContainsKey("LeftTime"))
	{
		DateTime deactivated = (DateTime)PhoneApplicationService.Current.State["LeftTime"];
		secondsSinceStart = (int)(DateTime.Now - deactivated).TotalSeconds + (int)PhoneApplicationService.Current.State["ElapsedTime"];
		writeTime();
		writeDate();
		timer.Start();
	}
	else secondsSinceStart = 0;
}

By using this method, I am able to keep a continuous timer, even when the user leaves my application.  If you were to ask any user, they would tell you that the application is always running.  The only indication they’ll get will be a quick glance at a “Resuming” screen that only shows up if your application loads slowly.  I actually had to force my app to pause so that I could take the following screenshot:

resuming

So that’s the basic story behind tombstoning.  Save your state on the way out, and restore it on the way back in.  Your users will never know the difference, and you’ll give them better battery life, performance, and user experience.

Download the Code

A more complicated example of the code I showed above, my timer runs infinitely (even in the background).  Press the Start button on the emulator to exit, and use the Back button to return.  There’s also a TextBox you can enter text into, and it will save it when you exit.

download

31 Days of Windows Phone | Day #13: Location Services

This post is Day #13 in a series called the 31 Days of Windows Phone.

Yesterday, we talked about the VibrateController on Windows Phone, and how we notify our users that they need to pay attention to what’s happening on their device.  Today, we’re going to talk about the LocationServices, and how we can get information about where their device is.

Why is location important?

As devices go, mobile phones have the ability to give you more customized information than nearly any other.  This is specifically relevant when we talk about the location of the phone.  Here’s some specific examples (that I’ve made up for this article).

Field Documentation App

Let’s pretend that I have an application that contains (or accesses via web) thousands of schematics, part lists, and documentation for all of the products and devices that we have built and service for our customers.  On most every device, I have to search for the customer I’m working with today, find the specific office or site I’ll be visiting, and then parse through the dozens of documents that might still meet my criteria.

By adding location data to this application, we remove the need for the user to use search at all.  If each document was also tagged with geolocation data, as we approach the building, the specific documents for that site could imediately become available.  If we can get a specific enough location on a large facility, we might even be able to determine which device you’re near.  Using a device’s location to determine the appropriate data to show is one way of enhancing your application with location data.

Golfing Application

I’ve seen many golfing applications that allow you to enter your scores, track your handicap, and even share that data with your friends.  There’s one, specifically, however that stands out in my mind.

This application, when it starts up, recognizes which golf course you are currently at.  It also lists ones that are nearby (in case you are en route), but not having to look up the course is an awesome feature.  In addition, it recognizes which hole you’re on, and what the distance to major landmarks on the course are (sandtraps, water, tree, green, etc.).  One of the coolest features I’ve seen, though, is the shot-by-shot analysis.  Each time I hit a club, I tell it which one it was.  As I head to where the ball is, it actually keeps track of how far I hit each club, and with enough data, can even recommend a club to me based on my distance to the green.  Absolutely amazing uses of location data.

Understanding Location Services

There are three ways we can get data about the device’s location.  GPS, cell-phone triangulation, and Wi-fi location.  Here’s a quick glance at the strengths and weaknesses of each:

locationsources

Before you start worrying about having to compare and contrast the data from three independent sources, take a look at the green cloud in the picture above.  Microsoft has provided us with a set of Location services.

Using Location Services on Windows Phone 7

I’ve written plenty so far, but nothing about the code required to make this happen.  Here’s the good news:  this might be one of the easiest things you do in code.  Just follow these steps:

  1. Create a new GeoCoordinateWatcher object.
  2. Create an event handler for when the user’s position changes.
  3. Grab the data when that event fires.

You’ll likely want to offer your user more functionality than this (and my sample code below does just that), but for the plain-and-simple example, here’s the code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using System.Device.Location;
using Microsoft.Phone.Tasks;

namespace Day13_LocationServices
{
	public partial class MainPage : PhoneApplicationPage
	{
		GeoCoordinateWatcher gcw;
		
		// Constructor
		public MainPage()
		{
			InitializeComponent();
			gcw.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(gcw_PositionChanged);
			gcw.Start();
		}

		void gcw_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
		{
			Latitude.Text = e.Position.Location.Latitude.ToString();
			Longitude.Text = e.Position.Location.Longitude.ToString();
		}

		
	}
}

Like the accelerometer on Day #11, the emulator does not actually have a way to get location data.  If you run the above code in the emulator, you’ll get no data.  (You can check GoeCoordinateWatcher.Status for this info).  However, using our good friend Reactive Extensions, we can emulate this data as well.

There is an outstanding article on MSDN about how to implement this, so I won’t try and trump their efforts here.  You can check out the MSDN article about Reactive Extensions and Location on Windows Phone here.

Download the Code

In my sample application, I tried to take advantage of as much of the Location services as I could.  I let the user choose between High and Default accuracies, start and stop the service, and even create a map of the current coordinates in the application.  Check it out.  Far more robust than the example above.

download

31 Days of Windows Phone | Day #12: Making A Phone Vibrate

This post is Day #12 in a series called the 31 Days of Windows Phone.

Yesterday, we talked about the accelerometer on Windows Phone, and how we can pretend to have a real device giving us data.  Today, we’re going to talk about the VibrateController, and how we can give feedback to our users about what is happening with our application.

Because telling someone how to make their phone vibrate immediately evokes tasteless jokes, I’ll let you get them out of your system here, before I have to write “vibration” 15 more times.  Go ahead…I’ll wait.

Why Make the Phone Vibrate?

There’s certainly a great number of silly and/or inappropriate reasons to make a phone vibrate.  For the purposes of this article, however, I’m going to cover some of the specific reasons you’d make the phone vibrate.

Game Feedback

Let’s start with the obvious one: games.  When you’re playing a game, you might not always be able to give the user all of the information they need on-screen.  (Especially when they’ve got their fingers on the screen.)  Giving them “haptic feedback” allows them to know they’re being attacked, or that they need to pay more attention to something important.

Button Feedback

This is probably going to be far more common for you, but for every button you have on your application, haptic feedback lets the user know they pressed the button appropriately.  Default buttons in Windows Phone turn a solid color when pressed, but many times users aren’t certain they made the click (especially if the action takes a few seconds to happen.)  Giving them a quick vibration lets them know they accomplished their goal.

Notifications

Another obvious, but underused opportunity for vibration feedback is notifications.  By default, if you get an email, text message, etc., your phone vibrates (or makes a noise).  We should leverage that same user experience in our applications.  When the user should be alerted to something, make the phone vibrate.  This is especially important when your application is a passive one.  For example, an application that tracks your location as you run through your neighborhood.  If it loses a signal, or perhaps you reach your target distance, a vibration would let the user know, without looking at their phone.  In that same example, you could even give them feedback each 1/4 mile, so that they’re aware of how far they’ve gone.

How Do I Make the Phone Vibrate?

Thankfully, this is incredibly simple.  You need two lines of code to make it happen, but you should spend a significant amount of time tweaking this to your specific needs.  Here’s the basic code:

VibrateController vc = VibrateController.Default;
vc.Start(TimeSpan.FromMilliseconds(100));

How long should I make it vibrate?

There aren’t any specific rules about how long vibration should happen for a specific notification, but I have some guidelines I follow, and I’ll share them with you:

  1. 1/10 of a second is the appropriate amount of time for a button press.  (It’s also the shortest amount of time the VibrateController can vibrate).
  2. 2 seconds = “WHAT IS WRONG WITH MY PHONE?!??!?” to your users.  2 seconds is WAY too long for any single notification.
  3. 300 milliseconds (~1/3 of a second) seems to be a good amount of time for one steady notification vibration.  It gets your user’s attention without making them think that something is wrong with their phone.
  4. Quick pulses of vibration are another great way to let the user know what is happening.  I have included this example in my sample code download below, but for a clearer explanation for how I’m doing it, check out my tutorial on “How To Create A SetTimeout Function In Silverlight.”

Download the Code

We’ve got some heavy-duty topics coming up in the next few days, including Location Services and Tombstoning.  Please leave a comment on any of the posts in this series to let me know what you think!

download