In this windows phone 7 development 201 article we are going to cover live tiles. Live tiles have become a staple mark in the Windows Phone 7 OS arsenal as it distinguishes itself from the rest of the competition. In addition, it also gives developers a little more real-estate when it comes to getting pertinent information to the end user. This information could be anything from a notification that a new item is available and can be denoted by a number encased in a black circle to a title and text under it.

For this article we are going to continue using the Client Contact Information project and add live tiles to it by adding a new page called “Settings.xaml”. This will not only be used for live tiles but any future improvements we will make to our application. We can start to look at the code below and see what we have done to the “Settings.xaml”.


//settings.xaml

<phone:PhoneApplicationPage
x:Class="WP7LDBStorage.Settings"
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"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480"
shell:SystemTray.IsVisible="True">

<!--LayoutRoot is the root grid where all page content is placed-->
<Grid x:Name="LayoutRoot" Background="Transparent">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

<!--TitlePanel contains the name of the application and page title-->
<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
<TextBlock x:Name="ApplicationTitle" Text="Client Contact Information" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="Settings" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>

<!--ContentPanel - place additional content here-->
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<CheckBox Content="Live Tile Enabled" Height="72" HorizontalAlignment="Left" Margin="6,6,0,0" Name="cbLiveTile" VerticalAlignment="Top" Width="444" Click="cbLiveTile_Click"/>
</Grid>
</Grid>

<!--Sample code showing usage of ApplicationBar-->
<!--<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
<shell:ApplicationBarIconButton IconUri="/Images/appbar_button1.png" Text="Button 1"/>
<shell:ApplicationBarIconButton IconUri="/Images/appbar_button2.png" Text="Button 2"/>
<shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem Text="MenuItem 1"/>
<shell:ApplicationBarMenuItem Text="MenuItem 2"/>
</shell:ApplicationBar.MenuItems>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>-->

</phone:PhoneApplicationPage>

In the code above we have the user interface for the settings page we have created. This page is designed to house all of the additions in future tutorials. We are going to start by adding in the ability too have a Live Tile when the user pins to the homescreen. To enable and disable the live tile when we want to, we included a checkbox to accomplish this. Later on in the tutorial we will cover how to make sure the checkbox stays checked when we exit the application. For now it seems that out user interface for the settings face has been appropriately fleshed out and we can move onto the backend of the page.


//settings.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;
using Microsoft.Phone.Shell;
using System.IO;
using System.IO.IsolatedStorage;

In the code above we are importing a couple key items located near the bottom. These include Microsoft.Phone.Controls, Microsoft.Phone.Shell, System.IO and System.IO.IsolatedStorage. All of these are pertinent to making live tiles functional and work correctly.


// Directive for the data model
using WP7LDBStorage.Model;

namespace WP7LDBStorage
{
public partial class Settings : PhoneApplicationPage
{
public Settings()
{
InitializeComponent();
IsolatedStorageFile directory = IsolatedStorageFile.GetUserStoreForApplication();
if (directory.FileExists("settings.txt"))
{
var textFound = "";
using (var myFileStream = new IsolatedStorageFileStream("settings.txt", FileMode.Open, IsolatedStorageFile.GetUserStoreForApplication()))
using (var reader = new StreamReader(myFileStream))
{
var text = reader.ReadToEnd();
textFound = text;
}

if (textFound == "1")
cbLiveTile.IsChecked = true;
else
cbLiveTile.IsChecked = false;
}
}

In the code above we are using the default constructor of the setting code file to create an IsolatedStorageFile variable. With that variable we use it in an if statement to determine if a text file with the name “settings”. If in fact the file does exist we want to open the file, read it all in and make the contents equal to a global variable. We then use that information to determine if the text in the variable is a one or a zero and make the checkbox checked or unchecked accordingly.


private void ApplicationBarIconButton_Click(object sender, EventArgs e)
{
// Return to the main page.
if (NavigationService.CanGoBack)
{
NavigationService.GoBack();
}
}

private void cbLiveTile_Click(object sender, RoutedEventArgs e)
{
if (cbLiveTile.IsChecked.Value)
{
IsolatedStorageFile directory = IsolatedStorageFile.GetUserStoreForApplication();
if (directory.FileExists("settings.txt"))
{
using (var myFilestream = new IsolatedStorageFileStream("settings.txt", FileMode.Truncate, IsolatedStorageFile.GetUserStoreForApplication()))
using (var writer = new StreamWriter(myFilestream))
{
writer.Write("1");
}
}

CreateLiveTile();
}
else
{
IsolatedStorageFile directory = IsolatedStorageFile.GetUserStoreForApplication();
if (directory.FileExists("settings.txt"))
{
using (var myFilestream = new IsolatedStorageFileStream("settings.txt", FileMode.Truncate, IsolatedStorageFile.GetUserStoreForApplication()))
using (var writer = new StreamWriter(myFilestream))
{
writer.Write("0");
}
}

ResetMainTile();
}
}

Above we have an event handler that attaches to the CheckBox we created to turn the live tile on and off for our application. To do this we check and see if the live tile checkbox is checked by getting the value. If it is then we need to create an IsolatedStorageFile variable and check to see that “settings.txt” is created and we want to use the Truncate function instead of just opening the file as we want to replace the current entry in the “settings.txt” with the variable we have now, either one or zero. after that we run a function called either “ResetMainTile();” or “CreateLiveTile();” depending on whether the checkbox is checked or not. We can now take a look at the functions mentioned above and see how to set the information on the live tile.


private void CreateLiveTile()
{
var appTile = ShellTile.ActiveTiles.First();

if (appTile != null)
{
var standardTile = new StandardTileData
{
Title = "Contact Info",
//BackgroundImage = new Uri("Images/SecondaryTileFrontIcon.jpg", UriKind.Relative),
Count = App.ViewModel.AllClientInfoItems.Count, // any number can go here, leaving this null shows NO number
BackTitle = App.ViewModel.AllClientInfoItems[App.ViewModel.AllClientInfoItems.Count-1].FirstName.ToUpper(),
//BackBackgroundImage = new Uri("Images/ApplicationTileIcon.jpg", UriKind.Relative),
BackContent = App.ViewModel.AllClientInfoItems[App.ViewModel.AllClientInfoItems.Count-1].LastName.ToUpper()
};

appTile.Update(standardTile);
}
}

Here we are creating a function called “CreateLiveTile” which is going to be used to create our live tile. We can start off by creating a variable called appTile which will be equal to the Live Tile or the first active live tile. It is key to not that multiple live tiles can be created from one application. Every other tile created, other than the first, can be a shortcut to a specific part of the application for easy navigation. We then want to see if there is a first tile and if there is we are going to give it some new StandardTileData through the variable standardTile. With a StandardTileData we are able to update things such as the title on the front side of the tile, the background image on the front and back of the live tile, the count (a number with a black circle around it on the front tile), the title on the back of the tile and the content on the back tile. With all of this extra information available to us to manipulate it makes things easier to display to the end user. We chose to show how many clients have been entered into the database, the name of the front title we changed to “Contact Info”, we left the background images as they were and the back title and content we changed to the First and Last name of the last person entered in the database respectively. After all of this information has been entered we can update the tile by calling the appTile.Update(standardTile); right after the information we filled in.


private void ResetMainTile()
{
ShellTile tile = ShellTile.ActiveTiles.First();
StandardTileData data = new StandardTileData
{
BackBackgroundImage = new Uri("LinkThatDoesntGoAnywhere", UriKind.Relative),
BackContent = string.Empty,
Count = 0,
BackTitle = string.Empty
};
tile.Update(data);
}

Above we have the function ResetMainTile() which is used when the checkbox to enable the live tile is disabled or unchecked. The variable we create for the first tile is a ShellTile object. After a live tile has been activated we have found it is difficult to return it to what it once was. In this case we found we could disable the tile flipping by referencing a background image that did not exist for the back tile. We emptied the BackContent and BackTitle and made the Count equal to zero. After this is complete, all that is left to do is call the Update function on the tile with the new data we have entered. If you were to navigate to the home screen, the tile would no longer flip with information but instead be static.


//MainPage.xaml

<!--Sample code showing usage of ApplicationBar-->
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
<shell:ApplicationBarIconButton x:Name="btnSubmit" IconUri="/Images/appbar.check.rest.png" Text="Submit" Click="btnSubmit_Click"/>
<shell:ApplicationBarIconButton x:Name="btnClear" IconUri="/Images/appbar.cancel.rest.png" Text="Clear Form" Click="btnClear_Click"/>
<shell:ApplicationBarIconButton x:Name="btnNumber" IconUri="/Images/appbar.share.rest.png" Text="# Of Entries" Click="btnNumber_Click"/>
<shell:ApplicationBarIconButton x:Name="btnSettings" IconUri="/Images/appbar.feature.settings.rest.png" Text="Settings" Click="btnSettings_Click"/>

<shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem x:Name="mItemAbout" Text="About" Click="mItemAbout_Click"/>
</shell:ApplicationBar.MenuItems>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>

In the code above we wanted to show you that we made another ApplicationBarIconButton to link the main page of the application to the settings page. We used a fancy cog as the icon and the event handler can be found below.


//MainPage.xaml.cs

private void btnSettings_Click(object sender, EventArgs e)
{
NavigationService.Navigate(new Uri("/Settings.xaml", UriKind.Relative));
}

Above code is used in the MainPage.xaml.cs and is an event handler used to send the user to the Settings page we have created previous. This is fairly old hat considering we have tackled this in previous tutorials but is always good to review.


//App.xaml.cs

// 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)
{
IsolatedStorageFile directory = IsolatedStorageFile.GetUserStoreForApplication();
if (!directory.FileExists("settings.txt"))
{
using (var myFilestream = new IsolatedStorageFileStream("settings.txt", FileMode.Create, IsolatedStorageFile.GetUserStoreForApplication()));
}
}

In the code above we are looking at App.xaml.cs which is crucial to the checkbox in the settings page. We call this when the application is launching from the start menu or the home screen. This code created an IsolatedStorageFile variable to check and see if the file “settings.txt” exists in the our Isolated Storage. If it does not, we need to create one so that we do not encounter problems later on in the application.

With all of this code complete we should now be able to see it in action. To do this we can go to the applications menu, and hold on our application and tell it to pin to the start screen. If you wait and be patient, we know how hard that is, you can see the live tile flip if the checkbox within the Settings page has been checked.

Now that the tutorial is complete, you should be able to successfully create a live tile for any application you develop from now on. You can explore what else is possible with live tiles as the possibilities are endless to the information you can display to your users. In the next tutorial we will explore push notifications and how we can do that without developing a large scale site/database to manage that. The gallery below shows the Client Contact Information working on the HTC Titan X310e. Until the next development tutorial, Happy Hacking!

[nggallery id=5]

Share This