Page view counter

Themes Revisited: The Implicit Style Manager [Updated!]

In a recent post on theming using the new Themes from the Controls Toolkit I showed that you can add a theme to your Xaml and then add a container as the content of that theme.

A powerful alternative is to use the ImplicitStyleManager to apply the theme to a single control or, more commonly, to a container (for example, a grid) and all its controls.

To do so, you'll want to provide the Silverlight URI to the .xaml file that defines the theme, which you can copy straight from the source code provided with the Toolkit into your project.

ThemeXamlInProject

Based on a question I received, I realized I should have provided more clarification:

The exact steps for adding this Xaml file are to go to the source files for the toolkit, navigate to the Themes pseudo-folder and grab Themes.xaml from under Controls.Theming.ShinyBlue and copy it to your project,  renaming it to Microsoft.Windows.Controls.Theming.ShinyBlue.xaml  (as shown).

This name is based on the fact that the file you are grabbing is from the Controls.Theming.ShinyBlue project and Controls is identified in the file as follows:

xmlns:controls="clr-namespace:Microsoft.Windows.Controls; assembly=Microsoft.Windows.Controls"

With that you are ready to create your page, which you can certainly lay out in either Blend or Visual Studio,

CreatingThemeTestInBlend

On clicking the Apply Theme in the upper left hand corner we'll apply the theme that is supplied as part of the control toolkit. We've already added the .xaml file that defines the ShinyBlue theme, so we need only add a reference to the Theme support dlls,

ThemeSupportDLLs

and the using statement at the top of Page.xaml.cs so that we can refer to the ImplicitStyleManager,

using Microsoft.Windows.Controls.Theming;

That done, we create the event handler to respond to the press of the Apply Theme button,

void applyTheme_Click( object sender, RoutedEventArgs e )
{

Within this method we'll create a Silverlight URI that points to the Xaml file. The URI constructor takes the Silverlight path to the ShinyBlue.xaml and the enumerated constant UriKind.Relative. With that, we are ready to call three static methods on ImplicitStateManager:

1. SetResourceDictionaryURI takes the control that we want to set the theme for (in our case the Layout Root, which will also apply the theme to all its contained controls) and the URI.

2. SetApplyMode again takes the control we're setting the theme for, but this time the second parameter is one of the ImplicitStyleApplyMode constants ( the possible values are Auto, OneTime or None).

3. Apply which applies the style and takes the single parameter of the control we're applying the style to.  Here is the complete Page.xaml.cs, with the code we've just discussed at the end.

using System;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Windows.Controls.Theming;

namespace ThemesWithISM
{
   public partial class Page : UserControl
   {
      public Page()
      {
         InitializeComponent();
         Loaded += new RoutedEventHandler( Page_Loaded );
      }

      void Page_Loaded( object sender, RoutedEventArgs e )
      {
         applyTheme.Click += new RoutedEventHandler( applyTheme_Click );
      }

      void applyTheme_Click( object sender, RoutedEventArgs e )
      {
         Uri uri = new Uri( @"ThemesWithISM;component/Microsoft.Windows.Controls.Theming.ShinyBlue.xaml", UriKind.Relative );
         ImplicitStyleManager.SetResourceDictionaryUri( LayoutRoot, uri );
         ImplicitStyleManager.SetApplyMode( LayoutRoot, ImplicitStylesApplyMode.Auto );
         ImplicitStyleManager.Apply( LayoutRoot );
      }
   }
}

 

 

 

Applying The Style

When the page is first displayed no style is attached,

BeforeApplyingTheme

Clicking on the Apply Theme button invokes the event handler which calls the ImplicitStyleManager methods and applies the theme,

AfterApplyingTheme

Published 31 October 2008 01:15 AM by jesseliberty
Filed under:

Comments

# kamil.svoboda said on 31 October, 2008 02:52 AM

Nice article! Thanks for it.

Although I think the setting of application style should be in Xaml. Can you explain how to use ImplicitStyleManager in Xaml? How can I get URI from theme file name for ImplicitStyleManager in Xaml? Thanks again.

Best regard,

Kamil

# Silverlight news for October 31, 2008 said on 31 October, 2008 06:32 AM

Pingback from  Silverlight news for October 31, 2008

# hmaprk said on 31 October, 2008 03:14 PM

Jesse,

Thanks for this post. The ability to apply a theme is something I have been waiting for for a while now.

I have not yet played around with themes(but I will soon). I assume it is like modifying any other resource dictionary? I am in the process of creating several reusable controls that I would like to include in different themes. Is it just a matter of adding a style/template in the resource dictionary with the appropriate targetType?

Thanks!

hmaprk - Hector (Tito) Aybar

# Community Blogs said on 31 October, 2008 04:56 PM

In this issue: John Stockton, Pierlag, Mel Lota, Ning Zhang, Carole Snyder, Martin Grayson, Jesse Liberty

# unruledboy2 said on 31 October, 2008 09:55 PM

I don't get it, do I specify the theme xaml files as source code or resource? both threw exception telling me that could not locate resource.

# unruledboy2 said on 31 October, 2008 09:57 PM

all the samples you provide as no orgnaizations for the namespace, for example, only "ThemesWithISM", not "Org.ThemesWithISM", does it cause the exception when I specify the full namespace?

# unruledboy2 said on 31 October, 2008 10:04 PM

and you mentioned that the theme is in dll, but your article did not show to deal with in any way. we could not see *.xaml files showed in your article.

# unruledboy2 said on 31 October, 2008 10:09 PM

the value of basics:TabControl of Property TargetType is invalid. [Line: 994 Position: 23]

the exception threw when I run the ImplicitStyleManager.SetResourceDictionaryUri.

any idea?

# unruledboy2 said on 31 October, 2008 10:14 PM

ok, now it works, here is my conclusion:

1. include theme xaml file as Code(NOT Resource)

2. include System.Windows.Controls, other wise you will get the exception as I mentioned above.

3. better wrap your code in utils or App as static function accepting FrameworkElement as parameter, like:

       public static void SetTheme(ref FrameworkElement Control, string Theme)

       {

           Uri uri = new Uri(@"Climbsoft.RegisterServer;component/" + Theme, UriKind.Relative);

           ImplicitStyleManager.SetResourceDictionaryUri(Control, uri);

           ImplicitStyleManager.SetApplyMode(Control, ImplicitStylesApplyMode.Auto);

           ImplicitStyleManager.Apply(Control);

       }

# Link-Sammlung #2 said on 01 November, 2008 06:53 AM

Pingback from  Link-Sammlung #2

# Link-Sammlung #2 said on 01 November, 2008 06:53 AM

Pingback from  Link-Sammlung #2

# jesseliberty said on 01 November, 2008 09:41 AM

unruledboy2 - yes all you are doing will work but is not necessary.  All you need to do is

Go to the source (which you can download at tinyurl.com/SLControlToolkit ) and navigate to the Themes pseudo-folder and grab Themes.xaml from under Controls.Theming.ShinyBlue and copy it to your project renaming it to Microsoft.Windows.Controls.Theming.ShinyBlue.xaml

This name is based on the fact that the file you are grabbing is from teh Controls.Theming.ShinyBlue project and Controls is identified in the file as follows:

 xmlns:controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls"

Once that file is added to your project, you'll add three references to your project:

Microsoft.Windows.Controls.Theming

Microsoft.Windows.Controls.Input

Microsoft.Windows.Controls.DataVisualization

and at the top of Page.xaml.cs you'll add

using Microsoft.Windows.Controls.Theming;

You can now create the URI as I showed:

        Uri uri = new Uri( @"ThemesWithISM;component/Microsoft.Windows.Controls.Theming.ShinyBlue.xaml", UriKind.Relative );

I apologize if I left any of these steps out or was unclear.

-jesse

# Silverlight in Style said on 01 November, 2008 11:24 PM

  We shipped the Silverlight Toolkit with the following Themes: Expression Dark Expression Light

# Customizing Silverlight Toolkit Themes | Tmao Coders said on 01 November, 2008 11:52 PM

Pingback from  Customizing Silverlight Toolkit Themes | Tmao Coders

# unruledboy2 said on 02 November, 2008 09:18 PM

@jesseliberty

no hard feeling at all, I was in a rush to make a demo for the collegues to show the development of sl2, because we are going to do a huge project. so my questions seem to be aggresive, sorry abou that.

and talking about the themes, normally we allow users to shift the theme they like, saving the settings locally or on server, so I wrap the logic into a function(or a separate class will be better) for easy reuse by all the pages.

thanks for your kind and detail reply. we love sl, though a lot need to be improved. :)

# redjackl said on 03 November, 2008 04:21 AM

Can we apply themes for controls that have controls templates using same approach?

# 2008 November 03 - Links for today « My (almost) Daily Links said on 03 November, 2008 04:28 AM

Pingback from  2008 November 03 - Links for today « My (almost) Daily Links

# Silverlight News for 3 November, 2008 said on 03 November, 2008 05:55 AM

Pingback from  Silverlight News for 3 November, 2008

# jimmccurdy said on 03 November, 2008 06:24 PM

I found a way to set the theme of a UserControl (or any FrameElement for that matter) in the XAML only.  Just include as follows:

<UserControl x:Class="MyUserControlClass"

xmlns="schemas.microsoft.com/.../presentation"

xmlns:x="schemas.microsoft.com/.../xaml"

xmlns:theming="clr-namespace:Microsoft.Windows.Controls.Theming;assembly=Microsoft.Windows.Controls.Theming"

theming:ImplicitStyleManager.ApplyMode="Auto"

theming:ImplicitStyleManager.ResourceDictionaryUri="MyThemeAssembly;component/MyTheme.xaml"

>

In this example, the theme URI refers to a separate project assembly called MyThemeAssembly, and a specific MyTheme.xaml within that assembly.  Of course, you don't need the assembly reference if it can be found in the same assembly.  Just be sure to set it's build action to "Resource".

# jimmccurdy said on 03 November, 2008 06:32 PM

One issue I am having with ImplicitStyleManager is as follows:

If I set the Style attribute on a Button (or other base control), which I do to set common Margins etc., then the ImplicitStyleManager does not apply its style to that control.  So I am struggling with how to set common layout attributes on the Button without screwing up the ImplicitStyleManager's style.  I really don't want to copying the individual layout attributes to every Button.

Any ideas?

# geek50 said on 04 November, 2008 07:44 PM

Error 1 The name 'applyTheme' does not exist in the current context

# geek50 said on 04 November, 2008 07:45 PM

Error 1 The name 'applyTheme' does not exist in the current context

# geek50 said on 04 November, 2008 07:46 PM

       void Page_Loaded(object sender, RoutedEventArgs e)

       {

           applyTheme.Click += new RoutedEventHandler(applyTheme_Click);

       }

Error 1 The name 'applyTheme' does not exist in the current context

# davex said on 06 November, 2008 04:38 PM

Can the theme be applied during the page-load as well, perhaps based on some user preference previously persisted in db?

Also, are there any performance considerations with respect to the apply mode used (none, once, auto)?

If you're looking for a new video to do - one that demonstrates retrieving the user's preferred theme using asp.net profile service and setting it dynamically within the silverlight application might be nice.  :)

Cheers!

Dave

# seeligd said on 06 November, 2008 08:41 PM

Hi Jesse -

Great article. I'm curious if it's possible to use the ImplicitStyleManager to allow derived controls to reference a single (parent) style?

For example, if I have ActionButton1 : Button and ActionButton2 : Button, is it possible to have them both reference a style with a TargetType of Button? When using generic.xaml, it was possible to set the DefaultStyleKey of a derived class to the parent and thereby obtain the parent's style. This doesn't seem to work with Implicit Styles but I wanted to be sure.

Here's a demo with the behavior in question:

http://drop.io/dnbyydm

Thanks!

# Shawn Burke's Blog said on 07 November, 2008 11:36 PM

The Silverlight Toolkit is off to a great start and lots of people have been spending time writing content

# derAndre said on 20 November, 2008 06:57 AM

Hi Jesse,

I wonder if it is possible to use definition from the ExpressionDark.xaml-file within the app.xaml-file.

Like this:

You have defined "ExpressionTopGradientBrush1" in the ExpressionDark.xaml

   ...

   <!--EXPRESSION DARK VALUES FOR CHARTS-->

   <Color x:Key="ExpressionTopGradientBrush1">#FFB5B5B5</Color>

   ...

I would like to use this Brush in a style definition in my App.xaml like this

   ...

   <Setter Property="Background" Value="{StaticResource ExpressionTopGradientBrush1}" />

   ...

is there a way to do this? Or is there another way to have "global" definitions which can be used in both files?

Best regards

André

# Star Pilot said on 02 December, 2008 10:17 PM

Jesse,

Any chance you could post the xaml for this example?

Thank you!

Philip

# Silverlight Toolkit Themes (Teil 1) at Programming with Silverlight, WPF & .NET said on 21 December, 2008 10:27 AM

Pingback from  Silverlight Toolkit Themes (Teil 1) at Programming with Silverlight, WPF &amp; .NET

# Silverlight Toolkit Themes (Teil 1) at Programming with Silverlight, WPF & .NET said on 21 December, 2008 10:47 AM

Pingback from  Silverlight Toolkit Themes (Teil 1) at Programming with Silverlight, WPF &amp; .NET

# lisamargaret said on 02 April, 2009 07:13 AM

Hi Jesse

thanks for the simple demonstration of applying themes to our silverlight applications. can we customize themes , like our own colors and fonts (styles rather) instead of the ones provided by the tool kit.

i really appreciate your help on it.

Thanks,

Lisa.