Getting Deep into .net

January 25, 2012

Dynamic Theme Switching in Silverlight Prism App

Filed under: How To,Prsim,Silverlight 4 — goldytech @ 5:10 pm
Tags:

 

INTRO

In my recent consulting assignment I was asked the question by one of the developer , that how can we get dynamic theming working in Prism application.My answer was that you can implement in the same manner as you do in the standard Silverlight application. But then he further asked that there are various regions in the RegionManager and how each views loaded in the different content regions can get unified theme , this encouraged me to try this out and see how it works.I started working on it and viola my answer was correct , there is no difference in implementing dynamic theming in prism specific app. In this blog post I explain you the same. I assume that readers are already aware of Prism library. If you are not then I strongly recommend that you acquire the knowledge of the same. In my example you will see the very basics of Prism app but the library has much more to offer.

GETTING STARTED

I created a very simple PRISM application which had only one Module (ModuleA). This module is loaded on demand when you click on the menu link which is under the ShellView.The application default gets loaded in the BlueTheme but it allows you to change the theme on the fly from the Themes menu. See the screen shot below of both themes.

 

blueThemeBlackTheme

 

The application has two content regions (MainContent and FooterContent).

Code Snippet
  1. <menu:Menu Grid.Row="0" HorizontalAlignment="Left" VerticalAlignment="Top">
  2.             <menu:MenuItem Header="Modules">
  3.                 <menu:MenuItem Header="Load Module A" Command="{Binding LoadModuleCommand}"/>
  4.             </menu:MenuItem>
  5.             <menu:MenuItem Header="Themes">
  6.                 <menu:MenuItem Header="Blue" Command="{Binding Path=ChangeThemeCommand}"
  7.                                        CommandParameter="BureauBlue.xaml"
  8.                                        IsChecked="{Binding IsBlueThemeSelected}"/>
  9.                 <menu:MenuItem Header="Black" Command="{Binding Path=ChangeThemeCommand}"
  10.                                        CommandParameter="ExpressionLight.xaml"
  11.                                        IsChecked="{Binding IsBlackThemeSelected}"/>
  12.             </menu:MenuItem>
  13.  
  14.         </menu:Menu>
  15.         <ContentControl prism:RegionManager.RegionName="MainContentRegion" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="12" />
  16.         <ContentControl prism:RegionManager.RegionName="FooterContentRegion" Grid.Row="2" Margin="12"/>

 
Let me show you the code which does the magic of dynamic theming.

Code Snippet
  1. public DelegateCommand<string> ChangeThemeCommand
  2.         {
  3.             get
  4.             {
  5.                 if (_changeThemeCommand == null)
  6.                 {
  7.                     _changeThemeCommand = new DelegateCommand<string>(x =>
  8.                     {
  9.                         Application.Current.Resources.MergedDictionaries.RemoveAt(0);
  10.                         var theme = Application.GetResourceStream(new System.Uri("/Shell;component/Assets/" + x, System.UriKind.Relative));
  11.                         var rd = (ResourceDictionary)(XamlReader.Load(new StreamReader(theme.Stream).ReadToEnd()));
  12.                         Application.Current.Resources.MergedDictionaries.Add(rd);
  13.                         if (x == "BureauBlue.xaml")
  14.                         {
  15.                             IsBlueThemeSelected = true;
  16.                         }
  17.                         else
  18.                         {
  19.                             IsBlackThemeSelected = true;
  20.                         }
  21.                     }, y => _moduleLoaded);//only allow to change themes when module is loaded
  22.                 }
  23.  
  24.                 return _changeThemeCommand;
  25.             }
  26.         }

The ChangeThemeCommand is DelegateCommand of String type. The command argument excepts the filename of theme. All theme files are located in Assets folders of the Shell project. The default theme is initialized in the App.xaml file with special syntax. It removes the current theme and loads the selected theme and merges it into the Resource Dictionary.

Code Snippet
  1. <Application.Resources>
  2.         <ResourceDictionary>
  3.             <ResourceDictionary.MergedDictionaries>
  4.                 <ResourceDictionary Source="/Shell;component/Assets/BureauBlue.xaml" />
  5.             </ResourceDictionary.MergedDictionaries>
  6.         </ResourceDictionary>
  7.     </Application.Resources>

This special syntax allows to access the files across different assemblies or xap files via relative paths.

CLOSURE

This was super simple to implement it and I highly recommend the devs to implement this feauture in their apps. Last a ninja tip. Always mark your assemblies in the module projects to CopyLocal=false if they are already referenced it in the Shell project. Download the sample code from here.

The Rubric Theme. Create a free website or blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 71 other followers