This article is Day #11 in a series called 31 Days of Mango.
Today, we’re going to cover Live Tiles on Windows Phone. This is a relatively big topic, but I think it’s possibly one of the most important ones you’ll read in this series. There are two specific points that I want to cover in this article: updating your primary Live Tile, and creating new secondary Live Tiles.
What Are Live Tiles?
We should probably start at the beginning on this one, because if you don’t have a Windows Phone, you might not know what an integral and awesome part of the operating system these really are. Here’s a quick look at my very animated home screen:
To get the disappointment out of the way, what we are going to be doing in this article doesn’t actually look like the lively animations you saw in the video above. (In fact, we currently don’ t even have a way to make animated tiles, other than to have them flip over, which we will cover.) What we are going to do, however, is provide new data to our user by updating the content on our Live Tiles from our app. We can do this two different ways: change the default values that a Live Tile exposes, or overwrite the entire tile background each time, effectively giving us much more creative control.
One important thing to remember, before we get started, is that Live Tiles reside on the home screen of your user’s device, and only the user can decide what tiles they will see. If you have an app that makes use of this functionality, make sure you let your users know that they should pin it to their home screen. Otherwise, all of your amazing effort might be lost on them.
Your App’s Default Tile
You may not realize this until you build an application yourself, but you have to create a tile for your application before you can submit it to the marketplace. All of this data is found in the WPAppManifest.xml file that you’ll find in your project inside the Properties folder. There are two specific parts of this document that I want to point out. The first is the App Title. It’s not directly related to the subject of this article, but it’s an important topic that you should be aware of. If you look in your XML file, you should see a line (Line #4 by default) that looks like this one:
The most important part in that example is the Title property. The text that you use here will be what the user sees when they are browsing their app list, as shown in the image below.
The other part of the XML that I want to to look at is the near the bottom (Line #25 by default), in the <Tokens> node. Here is what my <PrimaryToken> currently looks like for this application:
<PrimaryToken TokenID="Day11_LiveTilesToken" TaskName="_default">
<TemplateType5>
<BackgroundImageURI IsRelative="true" IsResource="false">Background.png</BackgroundImageURI>
<Count>20</Count>
<Title>Jeff Blankenburg</Title>
</TemplateType5>
</PrimaryToken>
</Tokens>
The values that I want you to notice are the BackgroundImageURI, the Count, and the Title. These are the properties that we will be changing throughout this article, and this location in your WMAppManifest.xml file is where you can set your initial values. (It’s important to remember that even though I am using Background.png in this example, you cannot use this icon for your final app, or you will be denied from the Windows Phone Marketplace.)
Using the values in the example above, we end up with an icon that looks like this:
You should notice that the Count value appears as a small black circle with white text, and the Title value appears at the bottom of the tile as white text. These colors, sizes, and layout do not ever change, even with theme changes by the user. The BackgroundImageURI will use the specified image to fill the entire space of the tile, regardless of its actual size, so it is highly recommended that your images for this purpose are 173px x 173px, as this is the size they will be rendered.
OK, now that we’ve covered off on how to create your initial tile for your application, I will spend the rest of this article showing you how to dynamically change your Live Tiles from your application. (Yes, Tiles is pluralized for a reason.)
Updating Your Primary Live Tile
As I mentioned at the beginning of this article, you have the ability to update your primary Live Tile, but you also have the ability to create and edit Secondary Tiles. This section will focus specifically on the Primary tile, and we’ll cover Secondary Tiles afterwards. Because there are many different options to how we can update a Live Tile, I’m going to start with a short video to show our final application in action, and exactly what it can do.
In order to this, we need to build that interface. In order to do that, you’ll need to include the smiley and sad face icons I’m using. Here they are, in all their downloading glory:
You will want to add them to your project, and set their content type to “Content” in your Visual Studio properties. If you haven’t done this before, right-click on your project, and choose “Add Existing Item…”
Once the images are in your project, clicking on one of them will bring up their Properties Panel. You want to make sure that your images are set to “Content” instead of “Resource.”
Once you’ve gotten those two images into your project, you can use the following XAML to create our entire interface, which will look like this:
You will see, in the XAML below, that we have two Image controls, a Slider and a TextBlock, a TextBox, and two Buttons. All of these controls allow us to create our customized Live Tile.
x:Class="Day11_LiveTiles.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
shell:SystemTray.IsVisible="True">
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="31 DAYS OF MANGO – DAY #11" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="live tiles" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<TextBlock Text="primary tile" Height="40" VerticalAlignment="Top" FontSize="26.667" />
<Image x:Name="SadButton" Source="images/sadface.png" Width="150" Height="150" Margin="191,48,115,0" VerticalAlignment="Top" MouseLeftButtonDown="SadButton_MouseLeftButtonDown" Opacity=".5" />
<Image x:Name="SmileButton" Source="images/smiley.png" Width="150" Height="150" HorizontalAlignment="Left" Margin="21,48,0,0" VerticalAlignment="Top" MouseLeftButtonDown="SmileButton_MouseLeftButtonDown" Opacity=".5" />
<Slider x:Name="CountSlider" Margin="8,198,102,0" Foreground="Green" Maximum="99" ValueChanged="CountSlider_ValueChanged" Height="84" VerticalAlignment="Top"/>
<TextBox x:Name="TitleText" Margin="8,250,102,288" TextWrapping="Wrap"/>
<TextBlock x:Name="SliderText" HorizontalAlignment="Right" Margin="0,181,12,0" TextWrapping="Wrap" Text="0" Width="90" FontSize="64" Height="84" VerticalAlignment="Top" TextAlignment="Center"/>
<TextBlock Text="secondary tile" Height="40" VerticalAlignment="Bottom" FontSize="26.667" Margin="0,0,0,133" />
<Button x:Name="SecondaryButton" Content="create a secondary tile" Height="75" Margin="5,0,102,56" VerticalAlignment="Bottom" Click="SecondaryButton_Click"/>
<Button x:Name="PrimaryButton" Content="update primary tile" Height="75" Margin="9,0,102,204" VerticalAlignment="Bottom" Click="PrimaryButton_Click"/>
</Grid>
</Grid>
</phone:PhoneApplicationPage>
Other than the new controls in the ContentPanel, the rest of the XAML above is the default code that Visual Studio creates for you in the MainPage.xaml file of a new project.
While you can download the entire application at the bottom of this article, the specific code we want to focus on in this section is related to what happens when we click the Button labeled “update primary tile.” In my PrimaryButton_Click event handler, the code looks like this:
{
ShellTile PrimaryTile = ShellTile.ActiveTiles.First();
if (PrimaryTile != null)
{
StandardTileData tile = new StandardTileData();
tile.BackgroundImage = new Uri("images/sadface.png", UriKind.Relative);
tile.Count = (Int32)Math.Round(CountSlider.Value, 0);
tile.Title = TitleText.Text;
PrimaryTile.Update(tile);
}
}
We create a reference to the primary tile by grabbing the First() item from the ActiveTiles collection. This collection includes not only the primary tile for your application (which will always be first), but any additional secondary tiles that you’ve created as well.
I created a new StandardTileData object, and then set the properties of this tile to be the “sadface” image, the Count to be the value of our slider, and the Title to be the value of our TextBox. Finally, we call the Update() method of the ShellTile object we created at the beginning, and pass the new tile data as the replacement. This is all that is required to update your tile, but don’t limit yourself to thinking that you have to use all of these values.
For example, if you have a weather application, and you want to show the temperature on your Live Tile, it might seem obvious to use the Count property to show that information. Since the Count property only goes up to 99, however, there are certain places that can have temperatures higher than 99, there’s a better way.
The easy solution would be to create a pile of images that have all of the possible values you’d want to show, and include them in your project. Then you could simply change the BackgroundImage property of the tile, and you’d have a custom temperature tile for your user. But this solution can end up causing you to create hundred of images that bloat the size of your app.
Thankfully, we can use images that we’ve stored on our web server (or less ethically, that someone else stored on their web server). To do this you can provide the BackgroundURI property an actual URL to an image, like the example below:
I’ve tried this with different image formats, and it really only seems to work with PNG files, so keep that in mind when you use this technique. It’s a great way to have a finite set of images living on your web server, and just grabbing them as you need them to meet certain conditions, like 58 degrees and cloudy.
Creating a Secondary Live Tile
So far, we have talked about how we can update the primary Live Tile that your application can have on the home screen. Now we are going to shift gears a bit and talk about secondary tiles. These are additional tiles that you can prompt your user to create for your application.
As an example, let’s say you have an application that allows a user to play several different games: Tic Tac Toe, WordSearch, and Hangman. The normal way your users will interact with your app is to open it from the App List, choose the game they want to play, and finally play that game. With secondary tiles, you could allow your user to create a separate tile for each of the games, so that they can find Hangman right on their home screen, and tap it to start playing. It works both as a shortcut to their favorite section of your app, as well as a constant reminder of your application on their home screen.
To do this requires nearly the same code that we used for the primary tile, with a few small distinctions. First, these secondary tiles may or many not be there when you’re looking for them. (The primary tile, even when it’s not pinned to the home screen, can be updated.) If the user deletes a secondary tile from their home screen, you don’t have access to it anymore.
The SecondaryButton_Click event handler method from our example earlier is shown below:
{
ShellTile SecondaryTile = ShellTile.ActiveTiles.FirstOrDefault(x => x.NavigationUri.ToString().Contains("ID=2"));
StandardTileData tile = new StandardTileData();
if (SecondaryTile == null)
{
tile.BackgroundImage = new Uri("images/yoda.png", UriKind.Relative);
tile.Title = "Beware…";
tile.BackTitle = "The Dark Side";
tile.BackBackgroundImage = new Uri("images/darthvader.png", UriKind.Relative);
tile.BackContent = "I…am your father.";
ShellTile.Create(new Uri("/DeepLink.xaml?ID=2", UriKind.Relative), tile);
}
}
You can see that in this example, I’m working some LINQ magic to find the specific Live Tile I’m looking for. I am looking for the tile in the ActiveTiles collection that has a NavigationUri that contains “ID=2.” Let me explain by starting at the end.
When you create a new secondary tile, you call the ShellTile.Create() method, where you pass it a URI and the new StandardTileData object you created. The URI needs to point to a page within your application, and there cannot be more than one secondary tile that points to the same URI. Therefore, the URI that you use acts like a unique indentifier for that secondary tile, and we will use LINQ to query against the collection of secondary tiles looking for the specific URI you used to create it. If several of your tiles point to the same page, but show different data, you can use the query string variables to make each URI unique, and then do your searches against that query string name and value, like my example above.
If, after our search, we didn’t find an existing tile, we can create one using the code above. You’ll notice that it’s the same StandardTileData object we used in the primary tile example, but that we have three more properties. (These properties can also be used for your primary tiles, but I wanted to reward those of you that have continued to read this far.)
In order to illustrate what these new properties are, I’ve got another short video for you below:
By specifying any of these three properties: BackTitle, BackBackgroundImage, or BackContent, your tile will automatically flip over. The OS handles when it flips over, you only get to indicate that it flips over. You should notice that the back of the tile does not have a Count property, just as the front of the tile does not have a Content property. Here are two screenshots of the two different sides of our tile:
You can allow your user to create as many secondary tiles as they’d like, just keep these details in mind:
- Each Live Tile must point to a unique URI location.
- Each time that you create a secondary tile, the user will be taken to their home screen to view it. You can’t create more than one secondary tile at a time.
- All of the properties shown in the code example above can be used on both your primary tile as well as any secondary tile.
- Cluttering up your user’s home screen is not always a good idea. Don’t give them a secondary tile unless there’s really a reason for one. It will get annoying.
Summary
The videos in this article should have summarized how these tiles behave in your application, but this is a very important way to interact with your users. Giving them relevant data on their home screen will not only remind them to use your app, but it will also allow them to see all of the information that is important to them directly on their home screen.
If you would like to play with a full, working version of the application that was demonstrated in this article, please click the Download Code button below.
Tomorrow, we are going to talk about an incredibly important topic for the success of your application: beta testing. Guest author Jared Bienz will walk you through exactly how to beta test your application, and how your application will benefit from it. See you then!
Leave a Reply