Using secondary shell tiles on Windows Phone with the 7.1 SDK

DZone 's Guide to

Using secondary shell tiles on Windows Phone with the 7.1 SDK

· Mobile Zone ·
Free Resource

Live Tiles are one of the key components that are specific to the Windows Phone platform and allow pushing informational messages much faster to the application users. Until now, a single application was tied to its unique Live Tile that would only show up if the user decided to pin the application on the home screen. Often, this was not very efficient because of specific situations when more than one live tile was needed. For example

  • A weather application that tracks multiple locations at once
  • A stock application that is tracking multiple indexes
  • A RSS reader that tracks several feeds for updates

You get the idea - applications can work with more than a single instance of the same content and it would be an overkill to try and include all information in a single Live Tile. With the updated (7.1) SDK, Microsoft introduced the concept of independent shell tiles, defined by the ShellTile class.

Take a look at this snippet:

ShellTile.Create(new Uri("/MainPage.xaml", UriKind.Relative), new StandardTileData()
    BackgroundImage = new Uri("isostore:/Shared/ShellContent/image.png", UriKind.Absolute),
    Title = "Sample"

This piece of code creates a new ShellTile that is automatically placed on the home screen. Once the user taps it, it will navigate to MainPage.xaml.

NOTE: The URI that is passed to a secondary tile should be relative. You cannot specify an absolute URI that would navigate to a specific web page, although there is a workaround that I will discuss later.

Then, I am passing an instance of StandardTileData, that implements ShellTileData - the base class that is used to pass tile information. I am directly setting the tile title and background image. Notice that the background image is loaded directly from the Isolated Storage through the isostore URI scheme that I discussed earlier.

NOTE: If the image that is passed to the tile is not found, the tile color will be set to the OS accent (theme) color.

There are also some additional properties that you can use in addition to the basic ones:

  • BackContent - used to display a string onthe back of the tile. The tile itself will automatically rotate betwen the base and secondary content.
  • BackTitle - the title to be displayed on the back of the tile.
  • Count - the count displayed in the corner of the tile. Only displayed on the front side of the tile.
  • BackBackgroundImage - the background image displayed on the back of the tile.
NOTE: Both BackgroundImage and BackBackgroundImage can be pointing to external resources (images outside the XAP or the isolated storage). It is recommended that those images are small enough to load quickly even with a slower Internet connection.

Each and every tile should have a unique URI to which it points. Otherwise, if an URI is already registered with another secondary tile, the new tile will not be added. So what to do if you decide that one of the tiles is expired and needs to be replaced?

First, you need to make sure that you are able to enumerate the tiles associated with the application. Those are accessible through the ShellTile.ActiveTiles IEnumerable:

foreach (ShellTile tile in ShellTile.ActiveTiles)

For each shell tile, you can either Update it (and pass a new instance of StandardTileData with updated content) or Delete it. You cannot (at this moment) read the associated metadata other than the navigation URI, which is considered to be the unique identifier for secondary tiles.

Generally, the additional tiles should not be created without user consent. But what if the application decides to do it? Take a look at this snippet:

void MainPage_Loaded(object sender, RoutedEventArgs e)
    for (int i = 0; i < 99; i++)
        ShellTile.Create(new Uri("/MainPage.xaml?" + i.ToString(), UriKind.Relative), new StandardTileData()
            BackgroundImage = new Uri("isostore:/Shared/ShellContent/image.png", UriKind.Absolute),
            Title = "Sample",
            BackContent = "Sample content",
            BackTitle = "BackTitle",
            Count = 10

Spot the problem. Theoretically, this should work just fine, even though new tiles will not provide any additional information to the user. As the application initializes, the loop is activated and the home screen becomes populated with tiles that are not necessary. Or does it?

The guys from the Windows Phone dev team predicted this kind of behavior, so whenever a new tile is added, the application is tombstoned and the user is switched to the home screen, so that he sees the new live tile. That way, the code above will throw an exception:

The worst that can happen with the scenario I described above is an application creating a single secondary tile and if the user will see that it's not exactly something he expected, he can easily remove the app.

I already mentioned that there is no way to directly invoke external resources through a Live Tile - the navigation URI should be relative to the application itself. However, you can do an interesting trick that will actually let the tile navigate to a web resource.

All you need to do is specify a parameter that will hold the web address:

var n = from c in ShellTile.ActiveTiles
where c.NavigationUri.ToString() == "/MainPage.xaml?uri=http://microsoft.com"
select c;

if (n.Count() == 0)
ShellTile.Create(new Uri("/MainPage.xaml?uri=http://microsoft.com", UriKind.Relative), new StandardTileData()
Title = "Microsoft Web"

Inside the page code-behind, check the parameter when the page is loaded, and if uri is not empty or null, start a WebBrowserTask to the URI specified in the parameter:

void MainPage_Loaded(object sender, RoutedEventArgs e)
        WebBrowserTask task = new WebBrowserTask();
        task.Uri = new Uri(NavigationContext.QueryString["uri"]);
    catch (KeyNotFoundException ex)
    { MessageBox.Show("No URI was passed to the app."); }

Time-wise, obviously you will have to give up a couple of seconds for the browser to load, being triggered from a third-party application, but ultimately - this can be a temporary solution, if necessary.


Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}