Friday, May 18, 2012

Creating updatable Live Tiles from A to Z (part 1)

Creating updatable Live Tiles from A to Z (part 1):
Something I haven’t found on the webs, is a nice overview of how to create updatable live tiles. Sure, you can gather all the data, but all the do’s and gotcha’s in one article would be nice. So I decided to get everything together myself.
OK: here’s the scenario. We need an app that visually shows information. Think about e.g. the mail-app that shows how many unread mails you have. Or a very nice one: Amazing Weather, which shows current weather conditions, and predictions. In our app we’ll show four arbitrary KPI’s on the tile, which will be updated in the background.

Step 1 : simple Tile

Your application can have one or several tiles on the start page( several if you implemented Deep link in your app), which can be reached by using the ShellTile.ActiveTiles collection. In my example there’s no deep link, so I should always get one tile, or none when not pinned to start. The Tile can be modified by passing it a ShellTileData-object. This way you can change front (Title, Count, BackgroundImage) and back (BackTitle, BackContent, BackBackgroundImage) of the tile. I will change the time whenever my app closes or deactivates :
1:  ShellTile tile = ShellTile.ActiveTiles.FirstOrDefault();

2:  if (tile!=null)

3:  {

4:      ShellTileData data = new StandardTileData()

5:      {

6:          Title = "12345",

7:          Count = 5,

8:          BackContent = "Some message...",

9:          BackBackgroundImage = new Uri("http://mw2.google.com/mw-panoramio/photos/medium/33672781.jpg"),

10:          BackTitle = "ABCDEF"

11:      };

12:   

13:      tile.Update(data);

14:  }




This gives me following result :

Front : Back :
1 2

Although this can already be handy for some scenario’s, it’s not enough. The count does not appear like in the mail-hub. Unfortunately. And I could show my KPI’s with text, but my Tile will be full of text, and maybe I’ll have more text than can fit on the Tile.

Step 2 : not so simple Tile


Remember my blogpost about saving pictures to the PicturesHub (over here) ? In there I showed you can create bitmapimages from any control. This is also what we’ll be doing when creating our tile-images. I start by creating a usercontrol. Best is to give it height and width equal to 173. This is the height/width for the tile. This will allow you to easily create your tile in a WYSIWYG-way. The usercontrol simply shows my four KPI’s by using “Trafficlights”, showing red, orange or green. I will also add white (or black if the light theme is being used) for “disaster”. Let’s start creating our usercontrol :
image

1:  <UserControl x:Class="PhoneApp1.Indicator"

2:      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

3:      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

4:      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

5:      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

6:      mc:Ignorable="d"

7:      FontFamily="{StaticResource PhoneFontFamilyNormal}"

8:      FontSize="{StaticResource PhoneFontSizeNormal}"

9:      Foreground="{StaticResource PhoneForegroundBrush}"

10:      d:DesignHeight="480" d:DesignWidth="480" Height="173" Width="173">

11:   

12:      <Grid x:Name="LayoutRoot" Background="{StaticResource PhoneAccentBrush}">

13:   

14:          <Grid.RowDefinitions>

15:              <RowDefinition Height="2*" />

16:              <RowDefinition Height="*" />

17:          </Grid.RowDefinitions>

18:          <Grid.ColumnDefinitions>

19:              <ColumnDefinition Width="2*" />

20:              <ColumnDefinition Width="*" />

21:          </Grid.ColumnDefinitions>

22:          <Rectangle Name="KPI1Indicator" Stroke="{StaticResource PhoneBorderBrush}" StrokeThickness="2" Fill="Red" Margin="80,80,10,10" RadiusX="20" RadiusY="20" />

23:          <Rectangle Name="KPI2Indicator" Grid.Column="1" Stroke="{StaticResource PhoneBorderBrush}" StrokeThickness="2" Fill="Green" Margin="3,80,30,10" RadiusX="20" RadiusY="20" />

24:          <Rectangle Name="KPI3Indicator" Grid.Row="1" Stroke="{StaticResource PhoneBorderBrush}" StrokeThickness="2" Fill="Orange" Margin="80,3,10,30" RadiusX="20" RadiusY="20" />

25:          <Rectangle Grid.Column="1" Grid.Row="1" Name="KPI4Indicator" Stroke="{StaticResource PhoneBorderBrush}" StrokeThickness="2" Fill="Yellow" Margin="3,3,30,30" RadiusX="20" RadiusY="20" />

26:      </Grid>

27:  </UserControl>




The four KPI-indicators need to be exposed to the outside word, so let’s add some properties for that :

1:  public Brush KPI1Brush

2:  {

3:      get { return KPI1Indicator.Fill; }

4:      set { KPI1Indicator.Fill = value; }

5:  }

6:   

7:  public Brush KPI2Brush

8:  {

9:      get { return KPI2Indicator.Fill; }

10:      set { KPI2Indicator.Fill = value; }

11:  }

12:   

13:  public Brush KPI3Brush

14:  {

15:      get { return KPI3Indicator.Fill; }

16:      set { KPI3Indicator.Fill = value; }

17:  }

18:   

19:  public Brush KPI4Brush

20:  {

21:      get { return KPI4Indicator.Fill; }

22:      set { KPI4Indicator.Fill = value; }

23:  }




When closing/deactivating the app, I will set the KPI-colors, and use this controls as image for the back of my tile. First, setting the colors:

1:  Indicator indicator = new Indicator();

2:   

3:  indicator.KPI1Brush = new SolidColorBrush(Colors.Black);

4:  indicator.KPI2Brush = new SolidColorBrush(Colors.Blue);

5:  indicator.KPI3Brush = new SolidColorBrush(Colors.Cyan);

6:  indicator.KPI4Brush = new SolidColorBrush(Colors.Green);


And then making a WriteableBitmap with it :

indicator.Measure(new Size(173, 173));
indicator.Arrange(new Rect(0, 0, 173, 173));

WriteableBitmap bm = new WriteableBitmap(indicator, null);


The Measure and Arrange-stuff is for making the control fit into a 173 by 173 square. Finally I need to save my image to Isolated Storage. Inside isolated storage I can store things in the Shared/Shellcontent-folder. This will also make it accessible by my tiles (info here).

1:  string indic = "/Shared/ShellContent/indicator.jpg";

2:   

3:  IsolatedStorageFile isolated = IsolatedStorageFile.GetUserStoreForApplication();

4:  if (isolated.FileExists(indic))

5:  {

6:      isolated.DeleteFile(indic);

7:  }

8:  IsolatedStorageFileStream stream = isolated.CreateFile(indic);

9:  bm.SaveJpeg(stream, 173, 173, 0, 100);

10:  stream.Flush();

11:  stream.Close();




And finally, I update my Tile to show the image from isolated storage :

1:  ShellTile tile = ShellTile.ActiveTiles.FirstOrDefault();

2:  if (tile!=null)

3:  {

4:      ShellTileData data = new StandardTileData()

5:      {

6:          Title = "12345",

7:          Count = 5,

8:          BackContent = "Some message...",

9:          BackBackgroundImage = 

10:              new Uri("isostore:/Shared/ShellContent/indicator.jpg", UriKind.Absolute),

11:          BackTitle = "ABCDEF"

12:      };

13:   

14:      tile.Update(data);

15:  }


and there you go :

1

In next blogpost I’ll tell you about updating the tile with a backgroundtask, which also has some gotcha’s you need to know.


>Follow @PiekenPuil







Tweet

No comments:

Post a Comment

Could not find a part of the path ... bin\roslyn\csc.exe

I am trying to run an ASP.NET MVC (model-view-controller) project retrieved from TFS (Team Foundation Server) source control. I have added a...