Frequently, when building a UI, one finds themself setting various appearance related properties over and over again. For example, you may want all the label text in your app to be a bold Trebuchet 12px font. This is easy to do with css in a web app, but not as straight forward with WinForms. WPF recognizes this need and satisfies it with the introduction of the ‘Style’ element. Let’s see how we would implement the above example in Xaml:
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type Label}">
<Setter Property="FontFamily" Value="Trebuchet" />
<Setter Property="FontSize" Value="12" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
</StackPanel.Resources>
<Label>Here is some text.</Label>
<Label>More text.</Label>
<Label>The last bit of text.</Label>
</StackPanel>
The basic and most common part of a style is its Setters. Simply declare the property name and its value and it will be applied. Easy, isn’t it? In my last post on data templates, I discussed how they could be applied by type or by key. The same applies to styles. In this case, I have scoped the style to the stackpanel; any label in that panel will pick up the style. I can, of course, override that style on the individual elements if I need. You can also inherit styles one from another by setting the BasedOn attribute of the style element:
<StackPanel>
<StackPanel.Resources>
<Style x:Key="baseStyle" TargetType="{x:Type Control}">
<Setter Property="FontFamily" Value="Trebuchet" />
<Setter Property="FontSize" Value="12" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
<Style BasedOn="{StaticResource baseStyle}" TargetType="{x:Type Label}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</StackPanel.Resources>
<Label>Here is some text.</Label>
<Label>More text.</Label>
<Label>The last bit of text.</Label>
</StackPanel>
Notice that I now have two styles; one that applies to all elements inherited from control, and a second one based on that style that extends it – the second style applies only to Label controls. I have taken this opportunity to show the second most common element you will find in a style: its Triggers collection. A trigger is a stateful aspect of the style. In this case, any of the labels in the stackpanel will appear red only when the mouse is hovering over them. Dang that’s cool!
By taking advantage of styles, you can create a consistent and easily maintainable appearance for your UI. There is a lot of power in this concept. However, sometimes you need to go farther. Suppose you want all of the buttons in your application to have a gel appearance. You cannot accomplish this with only basic style setters. In this case you need to use a control template. In order to understand what a control template is, you need to think of controls more abstractly. In WPF, a Button control is something akin to the platonic idea of a button. In your development experience you have seen many buttons of different shapes and styles, but they were all buttons. They typically all had some mouse over effect and triggered something when they were clicked. With WPF, all of the buttons you have seen could be implemented with the same Button control, but with different control templates. WPF, by way of control templates, allows you to switch out the appearance of any control, without having to write any code related to its functionality. Some controls have simple templates and some are complex. Here is a basic gel button template straight out of the SDK:

This control template is embedded within a style, but it does not have to be done this way. If you examine the ControlTemplate element, you will see where the look of the button is being defined. In this case it is simply a layering of rectangles with various gradients, but you have access to the full power of WPF in defining these templates (yes that includes 3D and animation if you so desire). Similar to styles, control templates can be assigned by type or key, but be careful that whatever template you are applying matches the control type you are applying it to. Every control expects to find certain pieces in its template in order to make the control work right. You should study a working template of a control before attempting to create your own. One of the best resources for learning about control templates is “simple styles”. Here you will find basic control templates for all of the major controls in WPF. They are accessible through the sidebar in Kaxaml (a tool you should try out anyway). You can also take advantage of control templating support in your own custom controls. A discussion of this is beyond the scope of this article. Watch Christopher Bennage’s blog for a post on this topic soon.
NEXT POST: WPF 3D and Animation
Posted
12-03-2006 5:19 PM
by
Rob Eisenberg