Thursday, May 3, 2012

Windows Phone 7 : Custom Themes (Load ResourceDictionary dynamically)

To change theme In windows phone 7, you can change background and accent colors from settings.

In WP7 development sometimes we require to create our own styles for application.

In this case we can create multiple resource Dictionary and apply on change of application accent color.

In this post we walk trough how to create custom themes and add dynamically on Application theme change.



I have created Three Themes Blue,Magenta and Default.

Step 1 : First Create ResourceDictionaries for Different themes and add styles for controls.

Blue.xaml

 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:System="clr-namespace:System;assembly=mscorlib">
    <Style x:Key="CommonBackgroundStyle"
           TargetType="Image">
        <Setter Property="Stretch"
                Value="None" />
        <Setter Property="Source"
                Value="/CustomThemeInWP7;component/Images/blue.png" />
    </Style>
    <Style TargetType="Button"
           x:Key="CommonButtonStyle">
        <Setter Property="HorizontalContentAlignment"
                Value="Center" />
        <Setter Property="VerticalContentAlignment"
                Value="Center" />
        <Setter Property="Margin"
                Value="5" />
        <Setter Property="Height"
                Value="70" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <Grid>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal" />
                                <VisualState x:Name="Pressed">
                                    <Storyboard>
                                       .....
                                       ..... 
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Border CornerRadius="10"
                                BorderBrush="Black"
                                BorderThickness="2"
                                Opacity="0.9"
                                x:Name="BackgroundBorder">
                            <Border.Background>
                                <LinearGradientBrush StartPoint="0,1"
                                                     EndPoint="1,1">
                                    <GradientStop Color="#0055FF"
                                                  Offset="0" />
                                    <GradientStop Color="#0E38E2"
                                                  Offset="5" />
                                    <GradientStop Color="#1640EA"
                                                  Offset="8" />
                                </LinearGradientBrush>
                            </Border.Background>
                        </Border>
                        <ContentPresenter Content="{TemplateBinding Content}"
                               HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                               VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

In Above snippet i have created styles for Image and Button for blue theme.

Step 2 : Same way create more resource Dictionary for other themes.

Step 3 : Apply created styles to controls in page.

MainPage.xaml

<Grid x:Name="LayoutRoot"
          Background="Transparent">
        <Image Style="{StaticResource CommonBackgroundStyle}" />
        <Grid HorizontalAlignment="Center"
              VerticalAlignment="Center">
            <StackPanel Orientation="Horizontal">
                <Button Content="OK"
                        Width="160"
                        Style="{StaticResource CommonButtonStyle}" />
                <Button Content="CANCEL"
                        Width="160"
                        Style="{StaticResource CommonButtonStyle}" />
            </StackPanel>
        </Grid>
 </Grid>


Step 4 : In constructor of App.xaml.cs write code to load resource Dictionary dynamically.


   public App()
   {
           
      UnhandledException += Application_UnhandledException;
      InitializeComponent();           
      InitializePhoneApplication();
           
      if (System.Diagnostics.Debugger.IsAttached)
      {               
          Application.Current.Host.Settings.EnableFrameRateCounter = true;            
               
          PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
      }
 



      //load resource dictionary daynamically
      var dictionaries = Resources.MergedDictionaries;
      dictionaries.Clear();
      string source = "";
      SolidColorBrush selectedTheme = (SolidColorBrush)Application.Current.Resources["PhoneAccentBrush"];
      SolidColorBrush blueBrush = 
              new SolidColorBrush() { Color = new Color() { A = 255, R = 27, G = 161, B = 226 } };
      SolidColorBrush magentaBrush =
              new SolidColorBrush() { Color = new Color() { A = 255, R = 216, G = 0, B = 115 } };
      if (selectedTheme.Color == blueBrush.Color)
      {
          source = String.Format("/CustomThemeInWP7;component/Themes/Blue.xaml");
      }
      else if (selectedTheme.Color == magentaBrush.Color)
      {
          source = String.Format("/CustomThemeInWP7;component/Themes/Magenta.xaml");
      }
      else
      {
          source = String.Format("/CustomThemeInWP7;component/Themes/Default.xaml");
      }
      var theme = new ResourceDictionary { Source = new Uri(source, UriKind.Relative) };
      dictionaries.Add(theme);
   }
 

In above code, first i get selected Accent Color  of application. then i am checking if color is blue, i will add Bule.xaml resource dictionary to Application.Current.Resources.MergeDictionaries.

if color is Magenta, i will add Magenta.xaml resource dictionary to Application.Current.Resources.MergeDictionaries.

else Default theme is applied.

So this way you can load resourceDictionary dynamically at runtime.

you can download code from below link.

Click WP7 Custom Theme To Download Source code.

No comments:

Post a Comment