C# WPF Styles


When you’re setting the look and feel of a UI, you may want to set the values of a group of properties. Ideally, you want to define the values of the properties only once and then apply that group of property settings to a number of different elements. In HTML, you can do this with Cascading Style Sheets (CSS). In WPF, you do it with styles.

In WPF you can collect a group of property settings into a style and then apply that style to many different elements.

  • Styles are declared as resources, as shown in the following code. As such, they can be applied to elements below them in the element tree.
  • There are two ways to define and apply styles—named styles and targeted styles.
  • With named styles, you give the style a name when you declare it. You then use the style’s name to explicitly apply it to selected elements.
  • With targeted styles, you give the style a target type when you declare it. The style is then automatically applied to elements of that type.
  • Setting a property locally on an object overrides any Style setting that might be on that property.
<Window.Resources>
<Style ...>
...
</Style>
</Window.Resources>

Named Styles

NamedStylesButton

The markup for this program is shown below.

<Window x:Class="StyleButton.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:StyleButton"
        mc:Ignorable="d"
        Title="Named Styles" Height="150" Width="325">
    <Window.Resources>
        <Style x:Key="myButtonStyle">
            <Setter Property="Button.Height" Value="40" />
            <Setter Property="Button.Width" Value="110" />
            <Setter Property="Button.FontSize" Value="16" />
            <Setter Property="Button.FontWeight" Value="Bold" />
        </Style>
    </Window.Resources>
    <StackPanel>
        <Button Style="{StaticResource myButtonStyle}">Button 1</Button>
        <Button Style="{StaticResource myButtonStyle}">Button 2</Button>
    </StackPanel>
</Window>
  • Use the x:Key attribute to name a style.
  • As with any resource, the key can be of any type, but it is usually a string.
  • By convention, the names of styles should end with the suffix Style.
  • The property values of a Style are set using elements called Setters. Setters require two attributes—a Property and a Value.
  • The Property attribute specifies which property of the target element should be set.
  • The property specified must be a dependency property.
  • For named styles, when assigning to the Property attribute of the Setter, it’s not sufficient to give just the property name—you must also include a class name as well.
  • The Value attribute specifies the value with which to set the target property. The values in the example code are simple, but for complex values you’ll need to use the attribute element syntax.

Since styles are declared as resources; you apply a named style to an element the same way you would apply the simple resources — using a markup extension of the StaticResource type.

Targeted Styles

Targeted styles are designed to be used on exactly one type of target element. The style is automatically applied to all elements of that type in the tree below the declaration. These are also called typed styles.

<Window x:Class="StyleButtonTarget.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:StyleButtonTarget"
        mc:Ignorable="d"
        Title="MainWindow" Height="150" Width="225">
    <Window.Resources>
        <Style TargetType="Button">
            <Setter Property="FontSize" Value="16" />
            <!-- No class name -->
            <Setter Property="FontWeight" Value="Bold"/>
        </Style>
    </Window.Resources>
    <GroupBox Header="Some Buttons" BorderBrush="Black" Margin="5">
        <StackPanel>
            <Button>Button 1</Button>
            <!-- No Explicit Application of the Style-->
            <Button>Button 2</Button> 
        </StackPanel>
    </GroupBox>
</Window>
  • In the style declaration set the TargetType attribute to the exact type of the elements on which to apply the style. The style will not be applied to elements of types derived from the specific type.
  • In the style declaration do not set the x:Key attribute. Setting the x:Key attribute inhibits the targeted style from being applied automatically.
  • In the style declaration the Setters do not require a class name with the property name. If you supply one, it must be the same as the TargetType.
  • In the target elements, the styles are applied automatically, so there is nothing to add to their declarations.

In the book Illustrated WPF, they have the following diagram.

StylesCompareDiagram

There are three more topics to consider when we are discussing styles: Setters, Event Setters and Triggers. Setters are elements in a Style that allow you to specify a property and a value with which to set the property. EventSetters are elements in a Style that allow you to attach an event handler to the Style. This allows you to execute procedural code, rather than just setting properties. Triggers are “conditional” styles, which apply only when a certain condition is met. There are five types of Triggers: simple Triggers, MultiTriggers, EventTriggers, DataTriggers, and MultiDataTriggers.

Leave a comment

Your email address will not be published. Required fields are marked *