Theme-aware Windows Phone 7 Icon Buttons

I’m not sure this is the best solution, but it works for me. Let me know if you can think of a better approach.

If you download the set of standard Windows Phone 7 icons, you’ll notice there are two sets: one for dark backgrounds, and one for light backgrounds. The built-in application bar magically picks the right icon, but if we want to use these icons for our own buttons, we need to switch between them.

The way I’m doing this is with two control templates for each button. Here’s a couple of examples for a Play and Pause button. Note that each button has the base circle, and the actual icon:

[code lang=”xml”]
<ControlTemplate x:Key="PlayButtonDark" TargetType="Button">
<Grid>
<Image Source="/Content/Images/AppBarIcons/dark/appbar.basecircle.rest.png"/>
<Image Source="/Content/Images/AppBarIcons/dark/appbar.transport.play.rest.png"/>
</Grid>
</ControlTemplate>
<ControlTemplate x:Key="PlayButtonLight" TargetType="Button">
<Grid>
<Image Source="/Content/Images/AppBarIcons/light/appbar.basecircle.rest.png"/>
<Image Source="/Content/Images/AppBarIcons/light/appbar.transport.play.rest.png"/>
</Grid>
</ControlTemplate>
<ControlTemplate x:Key="PauseButtonDark" TargetType="Button">
<Grid>
<Image Source="/Content/Images/AppBarIcons/dark/appbar.basecircle.rest.png"/>
<Image Source="/Content/Images/AppBarIcons/dark/appbar.transport.pause.rest.png"/>
</Grid>
</ControlTemplate>
<ControlTemplate x:Key="PauseButtonLight" TargetType="Button">
<Grid>
<Image Source="/Content/Images/AppBarIcons/light/appbar.basecircle.rest.png"/>
<Image Source="/Content/Images/AppBarIcons/light/appbar.transport.pause.rest.png"/>
</Grid>
</ControlTemplate>
[/code]

Then, I’ve got a little helper method and enum that helps me work out which theme is currently applied:
[code lang=”csharp”]
public static ThemeBackground CurrentThemeBackground()
{
var currentColor = (Color)Application.Current.Resources["PhoneBackgroundColor"];
if ( currentColor == Colors.Black )
return ThemeBackground.ThemeBackgroundDark;
else
return ThemeBackground.ThemeBackgroundLight;

}

public enum ThemeBackground
{
ThemeBackgroundDark,
ThemeBackgroundLight
}
[/code]

And finally, when my control is loaded, I can set the correct control template based on the theme:
[code lang=”csharp”]
private void UserControl_Loaded( object sender, RoutedEventArgs e )
{
switch ( UiHelper.CurrentThemeBackground() )
{
case ThemeBackground.ThemeBackgroundDark:
Play.Template = (ControlTemplate)Resources["PlayButtonDark"];
Pause.Template = (ControlTemplate)Resources["PauseButtonDark"];
break;
case ThemeBackground.ThemeBackgroundLight:
Play.Template = (ControlTemplate)Resources["PlayButtonLight"];
Pause.Template = (ControlTemplate)Resources["PauseButtonLight"];
break;
default:
throw new ArgumentOutOfRangeException();
}
}
[/code]

Like I say, if you can think of a better/cleaner way to do this, let me know!

Join the Conversation

11 Comments

    1. Hrmm yeah I don’t think you can put a binding expression in the middle of a value, but I could use some sort of valueconverter to output the composite string.

  1. http://bit.ly/9CGQz8 yep, you’ll need a converter to move the Uri to the ImageSource type. You can also put the converter into App.xaml as resources so you don’t have to duplicate between controls.

    See the Visibility setting below where we are using a VisibilityTrueConverter to set visibility of a Dialog depending on a boolean property in a view model:

    1. <localControls:DialogMessageControl x:Name=”DialogMessage” Canvas.ZIndex=”500″ Message=”{Binding DialogMessage}” Visibility=”{Binding IsDialogMessageVisible, Converter={StaticResource VisibilityTrueConverter}, Mode=TwoWay}” />

  2. I believe WP7 automatically converts white to black for the light background theme if you use the correct size .png (42 x 42 px) and have a white icon against a transparent background – at least, it worked for me; have a look at this decidedly average calendar icon i made and see if it does it automatically… http://yfrog.com/86calendar0p

  3. Hey thanks for this – would it also work for setting different background images depending on the theme? New to WP7 and VS/EB so simple terms much appreciated!

    Guess the code in the blog belongs in the MainPage.xaml? But as it is an image will I need to take on board (and try to get my head around) Keith’s contribution?

    Many thanks!

    1. Yes, if you want to bind an image to a location that changes at runtime, you’ll probably need an IValueConverter to convert from the location to a BitmapImage.

  4. With the release of the final dev tools, there’s a PhoneDarkThemeVisibility and PhoneLightThemeVisibility.

    Just create a dark and light icon in the same grid and bind the Visibility to the PhoneDarkThemeVisibility and PhoneLightThemeVisibility respectively.

Leave a comment

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: