Creating Round Image Button for WP7 (part 2)

Last time I showed you how I created a Round image Button for my Windows Phone 7 application. Today I am going to show you one of the ways to address a common issue with displaying images in your application that would need to be changed depending on the current theme in the phone.

First thing we need to be able to identify the current theme. We can query the current values of a few global resources such as PhoneBackColor, PhoneDarkThemeVisibility or PhoneLightThemeVisibility. The last two are not available in the public beta bits, so I will use the PhoneBackColor in the sample. When you query this resource, you should receive either black or white color value you could use to identify the theme.

As you remember for the Round Image button I've used one of stock images appbar.next.rest.png. It's an image with the transparent background and white arrow. Obviously it's not going be shown properly on a white background. So I opened this image in the Paint.net and filled the white arrow with the black color:

 I saved this image with the same name appbar.next.rest.png. In the project I create a folder Images with two subfolders Images\light and Images\dark and copied the light and dark copies of the image into the appropriate folders.

Next, we can create an image converter by implementing IValueConverter interface. Here's the full source for the ThemedImageConverter class:

     public class ThemedImageConverter : IValueConverter
    {
        private static  Dictionary<String, BitmapImage> imageCache = new Dictionary<string, BitmapImage>();
        private static Visibility currentTheme;
        private static string assetPath = "Images/light/";
       
        
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {           
            BitmapImage result = null;
            // Detect current theme
            this.DetectTheme((Color)parameter);
            // Path to the icon image
            string path = assetPath + (string)value;
            // Check if we already cached the image
            if (!imageCache.TryGetValue(path, out result))
            {
                Uri source = new Uri(path, UriKind.Relative);
                result = new BitmapImage(source);               
                imageCache.Add(path, result);
            }
 
            return result;
        }
      
        private void DetectTheme(Color color)
        {            
            Visibility lightThemeVisibility = Visibility.Collapsed;
            
            if (color == Colors.White)
            {
                lightThemeVisibility = Visibility.Visible;
            }
 
            // Check if the theme changed
            if (currentTheme != lightThemeVisibility)
            {
                currentTheme = lightThemeVisibility;
 
                if (lightThemeVisibility == Visibility.Visible)
                {
                    assetPath = "Images/light/";
                }
                else
                {
                    assetPath = "Images/dark/";
                }
            }
        }
         public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }
 
    }

As you can see from the code above the Convert method of this class receives the current value in the parameter of the back color and using it to identify the current theme in the DetectTheme method. After we identified the theme we can create a full path to the image file by combining the value from the "value" parameter and either the assetPath variable that will contain either "Images/light" or "Images/dark" folder names. All what's left after this is to make modifications to the XAML of the page. First we need to declare a static resource corresponding to the ThemedImageConverter:

 <phone:PhoneApplicationPage.Resources>                      
        <me:ThemedImageConverter x:Key="ThemedImageConverter" />
         ...
 </phone:PhoneApplicationPage.Resources>

 

And then we need to declare bindings for the converter and the parameters for the Image in the Button control as the following:

 <Grid x:Name="ContentPanel" Grid.Row="1" Margin="0,8,0,-8" >
        <Button  VerticalAlignment="Top" Style="{StaticResource RoundButton}" Height="72" Width="72" Margin="192,77,216,0" Click="Button_Click">
              <Image Source="{Binding Converter={StaticResource ThemedImageConverter}, ConverterParameter={StaticResource PhoneBackgroundColor}}"
              DataContext="appbar.next.rest.png" Height="42" Width="42" />
        </Button>           
</Grid> 

 

The ConverterParameter is assigned the value from the PhoneBackgroundColor static resource and the name of the image file is passed through the DataContext. As usual the attachement to this post contains the whole project that you can peruse for your needs.

In my last few posts I showed you how you can create a Round Image button control and one of the ways to make it to recognize the current theme on the phone and modiffy the image in the button appropriately to the selected theme.

 

StylingButtonD_L.zip