Styles in WPF

Styles in WPF allow us a reusable means of applying styling properties to controls. So for example, if we’ve decided that all the text boxes within a control, window or our app. should be displayed with a LemonChiffon background colour, instead of having something like this

<TextBox Background="LemonChiffon" x:Name="FirstName"/>
<TextBox Background="LemonChiffon" x:Name="LastName"/>
<TextBox Background="LemonChiffon" x:Name="Age"/>

we could create a style that’s applied to all TextBoxes, like the following

<ResourceDictionary>
   <Style TargetType="{x:Type TextBox}">
      <Setter Property="Background" Value="Gray" />
   </Style>
</ResourceDictionary>

...

<TextBox x:Name="FirstName"/>
<TextBox x:Name="LastName"/>
<TextBox x:Name="Age"/>

The style is defined as part of the ResourceDictionary and in this instance as no x:Key is set on the style resource it’s applied to all TextBoxes. If you were to create more than one style for a TextBox in this way, the last one defined is the one that will be used to style the TextBoxes. In such a situation where no key is defined, implicitly the key of x:Key=”{x:Type TextBox}” is used instead.

Note: We set the properties of the UIElement we wish to change using the Setter tag and the Property is obviously the property on the UIElement and the value is the value we wish to apply. I know, it’s obvious but I thought I’d mention it anyway.

So if you had a desire to have multiple background colours, for example maybe one colour for required fields and another for options, you would need to give one or both styles a key name to be used by the TextBox. For example

<Style x:Key="Required" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
   <Setter Property="Background" Value="LemonChiffon" />
</Style>

<Style x:Key="Optional" TargetType="{x:Type TextBox}">
   <Setter Property="Background" Value="BlanchedAlmond" />
</Style>

...

<TextBox x:Name="FirstName" Style="{StaticResource Required}"/>
<TextBox x:Name="LastName" Style="{StaticResource Required}"/>
<TextBox x:Name="Age" Style="{StaticResource Optional}"/>

If the Optional key didn’t exist then all TextBoxes without a style applied will take on the style without a x:Key.

Styles can also inherit from other styles, so let’s say we want to inherit from the newly created Required style for a TextBox and create a style based on it but which also adds a Bold font. We use the BasedOn attribute

<Style x:Key="Important" TargetType="{x:Type TextBox}" BasedOn="{StaticResource Required}">
   <Setter Property="FontWeight" Value="Bold" />
</Style>

So the “Important” style now inherits the LemonChiffon background and adds the Bold font.

Styles, of course, can be placed in other assemblies and referenced via an application using the Pack URI for example, in my App.xaml I could reference the xaml from an assembly as follows

<Application.Resources>
   <ResourceDictionary Source="pack://application:,,,/MyAssembly;component/Themes/generic.xaml" />-->
</Application.Resources>

Note: Whilst this code works, it doesn’t display the style at design time via the XAML designer. It will display at runtime.

Along with the “basic” styles of a control we can declare other styling attributes such as Triggers.

<Style x:Key="Required" TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
   <Setter Property="Background" Value="LemonChiffon" />
   <Style.Triggers>
      <Trigger Property="IsMouseOver" Value="True">
         <Setter Property="Background" Value="GreenYellow" />
      </Trigger>
   </Style.Triggers>
</Style>

In the above we not add the trigger to change the background colour when the mouse is over the control.

Note: IsMouseOver comes from the UIElement.