The Windows Phone ecosystem just got more mature. With the release of Windows Phone 7.5 (aka "Mango") in late September 2011, developers have a whole lot of new features with which to build compelling applications. Many of these features are ones that Windows Phone developers directly clamored for. So if you've been building apps for Windows Phone 7 and wanted more power, Mango is here to help you out. With apologies to David Letterman, here are the top 10 developer features in Windows Phone 7.5, in descending order.

#10: Silverlight 4 Features

As a Silverlight developer, when I came to the Windows Phone I was elated that it was based on Silverlight. But as someone who spent most of his time writing Silverlight 4, I had to adjust to the number of missing features I had become accustomed to using, including these:

  • implicit styling
  • data-binding features:
    • StringFormat
    • FallbackValue
    • TargetNullValue
    • IDataErrorInfo
    • INotifyDataErrorInfo
  • commanding support (i.e., ICommand)
  • CompositeTransform
  • OData support out of the box

I'm happy to report that Windows Phone 7.5 supports these Silverlight 4 features and now also supports Silverlight 4's Webcam APIs (I'll discuss this last feature later).

#9: Mixed XNA/Silverlight Projects

Microsoft XNA projects are primarily used to build games for the Windows Phone. Although this will continue to be true, XNA has a weak spot: screen building. Building the menu screens and other parts of the user interface (UI) in games is harder than it needs to be in XNA. That's where the hybrid Windows Phone Silverlight and XNA Application project type comes in.

In this new project type, a Silverlight application is created but adds the necessary pieces to support a content pipeline and game loop. By default, this new project creates separate Silverlight and Game pages to support a standard side-by-side approach of having Silverlight handle the page navigation and supporting rendering of XNA in separate pages. For example, for an XNA page in one of these projects, a PhoneApplicationPage is created, but no internal XAML is specified because the entire page is rendered using XNA. First you need to use a game loop on the XNA page. The template accomplishes this by creating a game loop in the constructor, creating the GameTimer object, and handling the Update and Draw methods XNA developers are used to, as shown in Figure 1.

public GamePage()
{
  InitializeComponent();

  ...

  // Create a timer for this page
  timer = new GameTimer();
  timer.UpdateInterval = TimeSpan.FromTicks(333333);
  timer.Update += OnUpdate;
  timer.Draw += OnDraw;
}

Next, the template uses a SharedGraphicsDeviceManager class to allow sharing of Silverlight and XNA on a particular page, as in Figure 2.

protected override void OnNavigatedTo(NavigationEventArgs e)
{
  // Get the current graphics device
  var graphics = SharedGraphicsDeviceManager.Current.GraphicsDevice;

  // Set XNA/Silverlight Sharing
  graphics.SetSharingMode(true);

  // Create a new SpriteBatch, which can be used to draw textures.
  spriteBatch = new SpriteBatch(graphics);

  // TODO: use this.content to load your game content here

  // Start the timer
  timer.Start();

}

In this case, it calls the SetSharingMode to tell the system to share XNA and Silverlight. The GraphicsDevice on the SharedGraphicsDeviceManager is the same one you would be used to as a XNA developer, so all the same operations work. There are similar approaches that allow you to even overlay Silverlight on top of an XNA game using the UIElementRenderer class.

#8: Background Transfer Service

Many applications need to download or upload content to and from their applications. Developers might opt to create background agents (discussed later in this article) to perform this task, but typically the first choice for enabling file transfer should be the background transfer service.

This service is designed to allow you to queue up file transfer (download and upload) to be performed by the operating system. The key here is to use the BackgroundTransferService class to make requests, as shown in Figure 3.

// Determine the source and destination
var serverUri = new Uri("http://shawntwain.com/anne.mp3");
var isoStoreUri = new Uri("/shared/transfers/anne.mp3"),
                          UriKind.Relative);

// Create the Request
var request = new BackgroundTransferRequest(serverUri, isoStoreUri);

BackgroundTransferService.Add(request);

The service can also be used for uploads, as in Figure 4.

// Determine the source and destination
var serverUri = new Uri("http://shawntwain.com/anne.mp3");
var isoStoreUri = new Uri("/shared/transfers/anne.mp3"),
                          UriKind.Relative);

// Create the Request
var request = new BackgroundTransferRequest(serverUri);

// Set options
request.UploadLocation = isoStoreUri;
request.Method = "POST";

BackgroundTransferService.Add(request);

The background transfer service imposes specific limits on how many requests can be made per application, whether such requests occur while the device is on battery, and whether they download only while on a non-cellular connection. Even so, for many cases using BackgroundTransferService is the right approach to performing transfers in Mango.

#7: Local Database

Although using serialized objects in Windows Phone's isolated storage is still a primary use case, there are times when storing data in a local database simplifies development. To this end, Mango now supports a local database option. This option is built on top of LINQ to SQL. The local database support is easily used as a code-first mechanism for creating a data store. For example, you can easily build a class and use attributes to specify the fields in the database, as Figure 5 shows.

[Table]
public class Game
{
  [Column(IsPrimaryKey=true, IsDbGenerated=true)]
  public int Id { get; set; }

  [Column]
  public string Name { get; set; }

  [Column]
  public DateTime ReleaseDate { get; set; }

  [Column]
  public double Price { get; set; }

  [Column]
  public int CoverUrl { get; set; }
}

From that you can support a context class that exposes each of the tables as an endpoint for LINQ queries, as shown in Figure 6.

public class MyContext : DataContext
{
  public MyContext()
    : base("DataSource=isostore:/myapp.sdf;")
  {
  }

  public Table<Game> Games;
}

The DataContext class will take each field that is of type Table and allow that table in the local database. The DataContext class also supports creating the database and some limited upgrading of the database schema. With this class, you can simply store and query data, as in Figure 7.

var  ctx = new MyContext();

// If needed, create the database
if (!_ctx.DatabaseExists())
{
  ctx.CreateDatabase();
}

var game = new Game()
{
  Name = "Gears of War",
  Price = 59.99,
  ReleaseDate = DateTime.Now
};

ctx.Games.InsertOnSubmit(game);
ctx.SubmitChanges();

var qry = from g in ctx.Games
          where g.Price > 50
          select g;

var results = qry.ToList();

In short, the local database story in Mango represents a simple but powerful way to handle relational, queryable data on the device.

#6: Image-Loading Performance

Windows Phone 7 had several issues with UI performance that Microsoft wanted to tackle and improve in Mango without breaking old code. One of the problems was that images were loaded on the UI thread, which meant (by default) that if you have a lot of images (e.g., in a ListBox's DataTemplate), the UI could be less responsive than you need. To combat this problem, Mango supports four options:

  • None: Images are loaded on the UI thread immediately.
  • DelayCreation: Images are loaded on a background thread (off the UI thread).
  • IgnoreImageCache: Images are always loaded via the universal resource identifier (URI) -- and not from cache for the URI.
  • BackgroundCreation: Images are decoded on a background thread (off the UI thread).

These options are in the CreateOptions enumeration and are bit-wise flags, so that you can combine them. For Mango, the default is BackgroundCreation, but in many cases you might want to delay creation as well, as in the following example:

                              <Image>                              <Image.Source>                              <BitmapImage CreateOptions="BackgroundCreation,DelayCreation"                              UriSource="http://shawntwain.com/st_eyesh.jpg" />                              </Image.Source>                              </Image>                              

You can see that you can specify this by using a BitmapImage object in the XAML for the Image's Source property. The flags can be combined in the XAML using a comma, as shown in the example.

#5: Scrolling Performance

List scrolling is greatly improved in Windows Phone 7.5. Instead of letting the control handle scrolling as it did in Windows Phone 7, Mango changes this default to allowing the operating system to handle the scrolling by default. This means that changes to properties of elements in the scrolling area are limited while the user is scrolling (or flicking). The result is a more user-friendly way to handle scrolling. If you need to handle scrolling at the control level (therefore getting better property/event access at the control level), you can opt out by specifying how scrolling is handled, using an attached property on the ScrollViewer class:

                              <ListBox x:Name="theList"                              ScrollViewer.ManipulationMode="Control" />                              

You should do this only if you need to revert to the pre-Mango behavior, as ManipulationMode is System by default.

#4: Live Tiles Improvements

Live tiles have had several big improvements. Here are several of the most noteworthy ones:

  • Live tiles now support in-app (or background agents) updating of the tiles through a new simple API.
  • Live tiles now have a back that is occasionally shown and can contain additional information.
  • You can have more than one live tile (called secondary tiles).

The ShellTile class supports managing live tiles, including iterating through live tiles and creating new ones. For example, you can get the main live tile (the one that users can pin manually) and modify it, as shown in Figure 8. You can see in Figure 8 that the StandardTileData class is used to specify both the front and back of a live tile. By retrieving the first tile from ShellTile class's ActiveTiles property, you can change the default live tile data by calling Update.

var tileData = new StandardTileData()
{
  Title = "My App",
  BackgroundImage = new Uri("background.png", UriKind.Relative),
  Count = 42,
  BackContent = "This is the back",
  BackTitle = "The Back",
  BackBackgroundImage = new Uri("http://foo.com/moonimage.jpg")
};

var myTile = ShellTile.ActiveTiles.FirstOrDefault();

// Update the tile
if (myTile != null)
{
  myTile.Update(tileData);
}

You can create secondary tiles as well by using the ShellTile class's Create method with the same StandardTileData class, like this:

ShellTile.Create(new Uri(uri, UriKind.Relative), tileData);

The important part of the Create method is that it takes a relative URI. All secondary tiles are to be used as deep links into your application. For example, imagine you were creating a weather application. This application could create secondary tiles for each city for which the user wanted to get weather information.

#3: Access to Camera Hardware

One glaring issue for certain types of applications was that prior to Mango you could not get real-time access to the camera. You could ask the phone to snap a picture and return it to you, but access to a live feed from the camera just wasn't possible. Mango changes this by giving you two options:

  • Silverlight 4's Webcam APIs
  • the PhotoCamera class

The PhotoCamera class is a simple wrapper around the camera to allow your application to take its own photos, as Figure 9 shows. You can see in the example in Figure 9 that the PhotoCamera class supports events for taking pictures as well as using the camera as a VideoBrush to show the viewfinder. This encapsulates the entire photo experience in your application without switching to the camera app on the phone.

var cam = new Microsoft.Devices.PhotoCamera();

// Fires when the capture is done, but the image isn't ready yet
cam.CaptureCompleted += cam_CaptureCompleted;

// So you need to wait for image to be ready too
cam.CaptureImageAvailable += cam_CaptureImageAvailable;

// Camera can be used as a VideoBrush so you can show the camera in the UI
viewfinderBrush.SetSource(cam);

In addition, you can handle the camera button to really complete the experience, as in Figure 10. In this way you can manage taking a picture in your application, or you can drop down to the Silverlight 4 Webcam API to support real-time access to the video frames from the camera if you need to do live processing of the stream.

// Fired when the user 1/2 pressed the camera button (e.g. Focusing)
CameraButtons.ShutterKeyHalfPressed += OnButtonHalfPress;

// Fires when the user presses the camera button
CameraButtons.ShutterKeyPressed += OnButtonFullPress;

// Fires when the user releases the camera button
CameraButtons.ShutterKeyReleased += OnButtonRelease;

#2: Fast Task Switching

Although tombstoning (the process of deactivating an app that a user navigates away from) gives the user a favorable experience of leaving and returning to applications, before Mango it was assumed that tombstoning might cause processes to go away more than was necessary on the phone. To rectify this issue, Mango supports fast task switching. This means that your application might not go away completely when the user interrupts it. The operating system is allowed to just pause your process (i.e., all threads are paused, all I/O is stopped), and if the user returns to it, the app could just "press play" on your process instead of asking you to rebuild your application's state.

To accomplish this, the Application class's Activated event includes information about whether the process was preserved. You can see this event in use in Figure 11. Note that you need to continue tombstoning your state in case the operating system needs to shut down the process, but in most cases restart of your application should be nearly instantaneous.

private void Application_Activated(object sender, ActivatedEventArgs e)
{
  if (e.IsApplicationInstancePreserved == false)
  {
    // Load data from the Phone's State
    _myData = PhoneApplicationService.Current.State["myData"] as MainViewModel;
  }
}

#1: Multitasking

Finally, the biggest piece missing in Windows Phone prior to Mango for most developers was the ability to run code in the background. You can now do this by using background agents. These agents come in four flavors:

  • Periodic agents -- Code that runs every 30 minutes (or so) to do short-lived processing
  • Resource-intensive agents -- Code that runs when the phone is being charged and on a non-cellular connection (e.g., Wi-Fi) for longer processing
  • Audio agents -- Code that interacts with the music player to support specifying what music is playing, going to the next/previous song in playlists, and so on
  • Streaming audio agents -- Code that actively handles streaming audio to the device (and decoding it) for audio apps that need to handle digital rights management (DRM) or authentication manually

Although these four options certainly do not solve all the background task use cases, they are meant to protect the user from badly behaving apps and affect the user's experience minimally. These agents live in a separate project that is shipped as a separate assembly as part of an application. The separate assembly is used to minimize the size of loading the background task into memory.

Each of these agents has specific criteria for when and how they work. Let's take the simple periodic task example. When you add a periodic agent project, a new project that contains a single ScheduledTaskAgent class is added to your solution. This class is used to run your code, as shown in Figure 12.

public class TaskScheduler : ScheduledTaskAgent
{
  protected override void OnInvoke(ScheduledTask task)
  {
    UpdateTile();
    NotifyComplete();
  }
}

As you can see in Figure 12, the OnInvoke method is called, providing information about the task, and you can just run whatever code you need to run in the background in this method. When you're done with your processing, calling NotifyComplete tells the operating system that the background task successfully executed. Before this method can be used, you'll have to register your periodic agent, as shown in Figure 13.

var taskName = "MyPeriodicTask";

var task = new PeriodicTask(taskName)
{
  Description = "My Task does nothing...yet."
};

if (ScheduledActionService.Find(taskName) == null)
{
  // New Task
  ScheduledActionService.Add(task);
}
else
{
  // Replace old Task
  ScheduledActionService.Replace(task);
}

You can see in Figure 13 that you need to create a PeriodicTask object that contains the metadata about your task. The PeriodicTask doesn't need to know about your agent class, as an app can have only one and it is wired up automatically by Visual Studio in your WMAppManifest.xml file.

Before you add your new task, you need to see whether the task exists. If it doesn't, you can call the ScheduledActionService class's Add method; otherwise you can call the Replace method to re-register the agent. Agents need to be registered every two weeks, so the standard practice is to re-register them on every start-up of your application.

More Great Mango Features to Explore

Whether you're a seasoned Windows Phone developer or just getting started, this list will give you a starting point for getting acquainted with the many great improvements and new features in Windows Phone 7.5. The features I've covered in this article are just my personal top 10. No doubt you will find other favorites as you explore Mango and tackle Windows Phone development projects.
 

Shawn Wildermuth ( swildermuth@adoguy.com) is a Microsoft MVP (C#), MCSD.NET, MCT, and the founder of Wildermuth Consulting Services, a company dedicated to delivering architecture, mentoring, and software solutions in the Atlanta area.