You can think of a Style as a convenient way to apply a set of property values to more than one element. For instance, consider the following TextBlock elements and their default appearance:
<TextBlock>My Pictures</TextBlock>
<TextBlock>Check out my new pictures!</TextBlock>
.png)
You can change the default appearance by setting the properties such as FontSize and FontFamily on each TextBlock element directly. However, if you want your TextBlock elements to share some properties, you can create a Style in the Resources section of your XAML file, as shown here:
<Window.Resources>
...
<!--A Style that affects all TextBlocks-->
<Style TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="FontFamily" Value="Comic Sans MS"/>
<Setter Property="FontSize" Value="14"/>
</Style>
...
</Window.Resources>
When you set the TargetType of your style to the TextBlock type, the style is applied to all the TextBlock elements in the window.
Now the TextBlock elements appear as follows:
.png)
This section contains the following subsections.
- Extending Styles
- Relationship of the TargetType Property and the x:Key Attribute
- Styles and Resources
- Setting Styles Programmatically
- Bindings, Dynamic Resources, and Event Handlers
Extending Styles
Perhaps you want your two TextBlock elements to share some property values, such as the FontFamily and the centered HorizontalAlignment, but you also want the text "My Pictures" to have some additional properties. You can do that by creating a new style that is based on the first style, as shown here:
<Window.Resources>
...
<!--A Style that extends the previous TextBlock Style-->
<!--This is a "named style" with an x:Key of TitleText-->
<Style BasedOn="{StaticResource {x:Type TextBlock}}"
TargetType="TextBlock"
x:Key="TitleText">
<Setter Property="FontSize" Value="26"/>
<Setter Property="Foreground">
<Setter.Value>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStop Offset="0.0" Color="#90DDDD" />
<GradientStop Offset="1.0" Color="#5BFFFF" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Style>
...
</Window.Resources>
Notice that the above style is given an x:Key. To apply the style, you set the Style property on your TextBlock to the x:Key value, as shown here:
<TextBlock Style="{StaticResource TitleText}" Name="textblock1">My Pictures</TextBlock>
<TextBlock>Check out my new pictures!</TextBlock>
This TextBlock style now has a HorizontalAlignment value of Center, a FontFamily value of Comic Sans MS, a FontSize value of 26, and a Foreground value set to the LinearGradientBrush shown in the example. Notice that we have overridden the FontSize value of the base style. If there is more than one Setter setting the same property in a Style, the Setter that is declared last takes precedence.
The following shows what the TextBlock elements now look like:
.png)
This TitleText style extends the style that has been created for the TextBlock type. You can also extend a style that has an x:Key by using the x:Key value. For an example, see the example provided for the BasedOn property.
Relationship of the TargetType Property and the x:Key Attribute
As shown in the first example, setting the TargetType property to TextBlock without assigning the style an x:Key causes the style to be applied to all TextBlock elements. In this case, the x:Key is implicitly set to {x:Type TextBlock}. This means that if you explicitly set the x:Key value to anything other than {x:Type TextBlock}, the Style is not applied to all TextBlock elements automatically. Instead, you must apply the style (by using the x:Key value) to the TextBlock elements explicitly. If your style is in the resources section and you do not set the TargetType property on your style, then you must provide an x:Key.
In addition to providing a default value for the x:Key, the TargetType property specifies the type to which setter properties apply. If you do not specify a TargetType, you must qualify the properties in your Setter objects with a class name, using the syntax Property="ClassName.Property". For example, instead of setting Property="FontSize", you must set Property to "TextBlock.FontSize" or "Control.FontSize".
Also note that many WPF controls consist of a combination of other WPF controls. If you create a style that applies to all controls of a type, you might get unexpected results. For instance, if you create a style that targets the TextBlock type in a Window, the style is applied to all TextBlock controls in the window, even if the TextBlock is part of another control, such as a ListBox.
Styles and Resources
You can use a style on any element that derives from FrameworkElement or FrameworkContentElement. The most common way to declare a style is as a resource in the Resources section in a XAML file, as shown in the preceding examples. Because styles are resources, they obey the same scoping rules that apply to all resources; where you declare a style affects where the style can be applied. If, for instance, you declare the style in the root element of your application definition XAML file, the style can be used anywhere in your application. If you create a navigation application and declare the style in one of the application's XAML files, the style can be used only in that XAML file. For more information on scoping rules for resources, see Resources Overview.
In addition, you can find more information about styles and resources in Shared Resources and Themes later in this overview.
Setting Styles Programmatically
To assign a named style to an element programmatically, get the style from the resources collection and assign it to the element's Style property. Note that the items in a resources collection are of type Object, so you must cast the retrieved style to a Style before assigning it to the Style property. For example, to set the defined TitleText style on a TextBlock named textblock1, do the following:
textblock1.Style = (Style)(this.Resources["TitleText"]);
Note that once a style has been applied, it is sealed and cannot be changed. If you want to dynamically change a style that has already been applied, you must create a new style to replace the existing one. For more information, see the IsSealed property.
You can create an object that chooses a style to apply based on custom logic. For an example, see the example provided for the StyleSelector class.
Bindings, Dynamic Resources, and Event Handlers