Managing Silverlight Styles with ImplicitStyleManager
In a previous article I wrote about how styles can be defined and assigned to controls. While the default technique of defining and applying styles works, it certainly can be a pain to add Style="{StaticResource YourStyleKey}" to all of the controls needing to pick-up a specific style in an application. WPF provides a way to "implicitly" apply styles to controls but this functionality isn't available in Silverlight 2 unfortunately. Enter the ImplicitStyleManager provided by the Silverlight Toolkit. By using ImplicitStyleManager styles that target a specific control type can be applied without manually adding a Style attribute to each control. The class lives in the Microsoft.Windows.Controls.Theming namespace (Microsoft.Windows.Controls assembly) which needs to be referenced in the XAML file as shown next:
<UserControl x:Class="..." xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls" xmlns:theming="clr-namespace:Microsoft.Windows.Controls.Theming;assembly=Microsoft.Windows.Controls.Theming" >
Here's an example of using ImplicitStyleManager within a control that has styles defined locally within its Resourcessection:
<StackPanel> <Border BorderBrush="Green" BorderThickness="2" Padding="5" Margin="5" theming:ImplicitStyleManager.ApplyMode="OneTime"> <Border.Resources> <Style TargetType="Button"> <Setter Property="Foreground" Value="Green" /> </Style> <Style TargetType="TextBox"> <Setter Property="FontSize" Value="10.5"/> <Setter Property="FontFamily" Value="Trebuchet MS"/> <Setter Property="Foreground" Value="#FF00FF00" /> </Style> </Border.Resources> <StackPanel> <Button Content="Button inside border" /> <TextBox Text="TextBox inside border"></TextBox> </StackPanel> </Border> <Button Content="Button outside border" /> </StackPanel>
This example applies the styles to the appropriate controls (a Button and a TextBox in this case) automatically. The theming:ImplicitStyleManager.ApplyMode attribute makes this possible. Looking at the control definitions in the StackPanel you'll see that no Style attribute is added. Instead, the styles are "implicitly" applied based on the Style element's TargetType. You may also note that no x:Key is defined on the Style elements since it's not needed.
ImplicitStyleManagercan also be used to apply styles defined in a theme file (a XAML file containing a ResourceDictionary section) as shown next:
<Border BorderBrush="Green" BorderThickness="2" Padding="5" Margin="5" theming:ImplicitStyleManager.ApplyMode="OneTime" theming:ImplicitStyleManager.ResourceDictionaryUri="Theming/CustomTheme.xaml"> <StackPanel> <Button Foreground="White" Content="This is a button" Width="200" /> <CheckBox></CheckBox> <TextBox Text="Are you hungry?" /> <ListBox Height="40"> <ListBoxItem Content="This is an item" /> <ListBoxItem Content="This is an item" /> <ListBoxItem Content="This is an item" /> <ListBoxItem Content="This is an item" /> <ListBoxItem Content="This is an item" /> <ListBoxItem Content="This is an item" /> <ListBoxItem Content="This is an item" /> <ListBoxItem Content="This is an item" /> </ListBox> </StackPanel> </Border>
A portion of the CustomTheme.xaml file referenced by the code above is shown next:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Style TargetType="Button"> <Setter Property="IsEnabled" Value="true"/> <Setter Property="IsTabStop" Value="true"/> <Setter Property="Background" Value="#FF003255"/> <Setter Property="Foreground" Value="#FF313131"/> <Setter Property="MinWidth" Value="5"/> <Setter Property="MinHeight" Value="5"/> <Setter Property="Margin" Value="0"/> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="Cursor" Value="Arrow"/> <Setter Property="FontSize" Value="11"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <!-- Template Code --> </ControlTemplate> </Setter.Value> </Setter> </Style> <!-- Additional Control Styles –> </ResourceDictionary>
You can see that by using the ImplicitStyleManageryou can more easily create different themes that can be applied to controls without having to explicitly declare a Style attribute on each control. This allows for much greater flexibility than is available out of the box in Silverlight 2.