Skin your Silverlight 3 app with Implicit Style Manager

Silverlight 3 do not have implicit style like WPF or a Theming feature like ASP.NET which means you can’t [automatically] apply a Style to every Button of the app like in ASP.NET for example.

In Silverlight 3 you need to explicitly set styles on every controls.

Good news is you can find in the free Silverlight Toolkit the ImplicitStyleManager control that allows implicit styling to be applied to any control in a container by defining 2 attached properties.

 

Applying Theme in Silverlight 3 (auto Style)

Define your styles in a XAML resource dictionary file (like you already do) and set its build action to Content. Then reference it via the ResourceDictionaryUri attached property on a container of your page:

<Canvas themingToolkit:ImplicitStyleManager.ApplyMode="OneTime"
        themingToolkit:ImplicitStyleManager.ResourceDictionaryUri="Assets/ShinyBlue.xaml">

The ApplyMode has 3 values: None, OneTime and Auto.

  • None: Theme not applied
  • OneTime: Theme applied once after page load
  • Auto: Dynamic controls added at runtime will also be styled.

Inside the container (Canvas in my sample), controls are defined normally (I removed the Canvas.* for brevity):

<TextBox Text="TextBox" Width="125" />
<PasswordBox Width="125" />
<ProgressBar IsIndeterminate="False" Maximum="1" Value="0.5"/>
<RadioButton Content="RadioButton 1" IsChecked="True" />
<RadioButton Content="RadioButton 2"/>
<CheckBox Content="CheckBox 1"/>
<CheckBox Content="CheckBox 2" IsChecked="True"/>
[…]

And at runtime they automatically have styles applied to them!

ImplicitStyleManager sample

If you don’t want to build your Theme from scratch you’ll find some samples in the toolkit as well.

Silverlight Toolkit Themes

http://www.codeplex.com/wikipage?ProjectName=Silverlight&title=Silverlight%20Toolkit%20Overview%20Part%203&referringTitle=Home

The XAML files used by those themes can be found on your local folder after installing the toolkit, for the October 2009 toolkit it is located there:

C:\Program Files\Microsoft SDKs\Silverlight\v3.0\Toolkit\Oct09\Themes\Xaml

 

In my sample I use the ShinyBlue.xaml Theme and apply it via ImplicitStyleManager.

You can find more style in the Expression Community Gallery:
http://gallery.expression.microsoft.com

 

Specific Theme controls

You can also use the Theme Containers controls to apply Themes from the Silverlight Toolkit. These controls use ImplicitStyleManager and one of the external xaml resource dictionary file under the hood.

So applying ShinyBlue Theme is simply done via:

<shinyBlue:ShinyBlueTheme>
    <Grid>
        ...
    </Grid>
</shinyBlue:ShinyBlueTheme>

The shinyBlue prefix refers to the assembly containing the ShinyBlueTheme control (from the toolkit):

xmlns:shinyBlue="clr-namespace:System.Windows.Controls.Theming;
assembly=System.Windows.Controls.Theming.ShinyBlue"

 

Changing Theme at runtime

Suppose you have several themes and would like your users to be able to switch theme at runtime.
In my sample I add another theme (ShinyRed) from the toolkit and move both files to Assets/Themes folder:


Don’t forget to mark your xaml files as “Content” (build action).

Let’s add a “Theme selector” with a ComboBox + Button:

<ComboBox x:Name="cbThemes">
    <ComboBoxItem Content="ShinyBlue" Tag="ShinyBlue.xaml" />
    <ComboBoxItem Content="ShinyRed" Tag="ShinyRed.xaml"/>
</ComboBox>
<Button Content="Apply" Click="Button_Click" />

On the Button_Click eventHandler get the selected Theme and apply it with some static methods of the ImplicitStyleManager class:

private void Button_Click(object sender, RoutedEventArgs e)
{
    if (cbThemes.SelectedItem != null)
    {
        Uri uri = new Uri(String.Format("Assets/Themes/{0}", 
((ComboBoxItem)cbThemes.SelectedItem).Tag.ToString()), UriKind.Relative); ApplyTheme(uri); } } private void ApplyTheme(Uri uri) { ImplicitStyleManager.SetResourceDictionaryUri(LayoutRoot, uri); ImplicitStyleManager.SetApplyMode(container, ImplicitStylesApplyMode.Auto); ImplicitStyleManager.Apply(container); }

Now we are able to switch the current Theme live:

 

Dynamic list of available Themes

Let’s go further and list available themes at runtime.

With the help of this small unzip utility for Silverlight:

http://www.sharpgis.net/post/2009/04/21/REALLY-small-unzip-utility-for-Silverlight.aspx

we are able to automatically populate the ComboBox with Themes from the xap (the code below assume that your xaml themes files are located in a Assets/Themes folder - which contains only those files):

public DynamicStyle()
{
    InitializeComponent();

    this.Loaded += new RoutedEventHandler(DynamicStyle_Loaded);
}

void DynamicStyle_Loaded(object sender, RoutedEventArgs e)
{
    WebClient wc = new WebClient();
    wc.OpenReadCompleted += (s, args) =>
    {
        if (args.Error == null)
        {
            UnZipper unzip = new UnZipper(args.Result);

            List<ComboBoxItem> lstComboBoxItem = new List<ComboBoxItem>();

            ComboBoxItem item;
            string fileName;

            foreach (string filePath in unzip.GetFileNamesInZip())
            {
                if (filePath.StartsWith("Assets/Themes"))
                {
                    fileName=filePath.Replace("Assets/Themes/", string.Empty)
.Replace(".xaml", string.Empty); item = new ComboBoxItem(); item.Content = fileName; item.Tag = filePath; lstComboBoxItem.Add(item); } } cbThemes.ItemsSource = lstComboBoxItem; } }; wc.OpenReadAsync(new Uri("FunWithImplicitStyleManager.xap",
UriKind.RelativeOrAbsolute)); }

UnZipper is a utility class from the link above, and you’ll find it in my sample code.

Note you could also add code to persist the chosen theme during user session (or even between sessions with IsolatedStorage).

 

Download the source code

 

Technorati Tags:

1 Comment

Comments have been disabled for this content.