TOC

The community is working on translating this tutorial into Ukrainian, but it seems that no one has started the translation process for this article yet. If you can help us, then please click "More info".

Styles:

Using WPF styles

In the previous chapter, where we introduced the concept of styles, we used a very basic example of a locally defined style, which targeted a specific type of controls - the TextBlock. However, styles can be defined in several different scopes, depending on where and how you want to use them, and you can even restrict styles to only be used on controls where you explicitly want it. In this chapter, I'll show you all the different ways in which a style can be defined.

Local control specific style

You can actually define a style directly on a control, like this:

<Window x:Class="WpfTutorialSamples.Styles.ControlSpecificStyleSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ControlSpecificStyleSample" Height="100" Width="300">
    <Grid Margin="10">
        <TextBlock Text="Style test">
            <TextBlock.Style>
                <Style>
                    <Setter Property="TextBlock.FontSize" Value="36" />
                </Style>
            </TextBlock.Style>
        </TextBlock>
    </Grid>
</Window>

In this example, the style only affects this specific TextBlock control, so why bother? Well, in this case, it makes no sense at all. I could have replaced all that extra markup with a single FontSize property on the TextBlock control, but as we'll see later, styles can do a bit more than just set properties, for instance, style triggers could make the above example useful in a real life application. However, most of the styles you'll define will likely be in a higher scope.

Local child control style

Using the Resources section of a control, you can target child controls of this control (and child controls of those child controls and so on). This is basically what we did in the introduction example in the last chapter, which looked like this:

<Window x:Class="WpfTutorialSamples.Styles.SimpleStyleSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="SimpleStyleSample" Height="200" Width="250">
    <StackPanel Margin="10">
        <StackPanel.Resources>
            <Style TargetType="TextBlock">
                <Setter Property="Foreground" Value="Gray" />
                <Setter Property="FontSize" Value="24" />
            </Style>
        </StackPanel.Resources>
        <TextBlock>Header 1</TextBlock>
        <TextBlock>Header 2</TextBlock>
        <TextBlock Foreground="Blue">Header 3</TextBlock>
    </StackPanel>
</Window>

This is great for the more local styling needs. For instance, it would make perfect sense to do this in a dialog where you simply needed a set of controls to look the same, instead of setting the individual properties on each of them.

Window-wide styles

The next step up in the scope hierarchy is to define the style(s) within the Window resources. This is done in exactly the same way as above for the StackPanel, but it's useful in those situations where you want a specific style to apply to all controls within a window (or a UserControl for that matter) and not just locally within a specific control. Here's a modified example:

<Window x:Class="WpfTutorialSamples.Styles.WindowWideStyleSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="WindowWideStyleSample" Height="200" Width="300">
    <Window.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="Foreground" Value="Gray" />
            <Setter Property="FontSize" Value="24" />
        </Style>
    </Window.Resources>
    <StackPanel Margin="10">
        <TextBlock>Header 1</TextBlock>
        <TextBlock>Header 2</TextBlock>
        <TextBlock Foreground="Blue">Header 3</TextBlock>
    </StackPanel>
</Window>

As you can see, the result is exactly the same, but it does mean that you could have controls placed everywhere within the window and the style would still apply.

Application-wide styles

If you want your styles to be used all over the application, across different windows, you can define it for the entire application. This is done in the App.xaml file that Visual Studio has likely created for you, and it's done just like in the window-wide example:

App.xaml

<Application x:Class="WpfTutorialSamples.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
	 StartupUri="Styles/WindowWideStyleSample.xaml">
    <Application.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="Foreground" Value="Gray" />
            <Setter Property="FontSize" Value="24" />
        </Style>
    </Application.Resources>
</Application>

Window

<Window x:Class="WpfTutorialSamples.Styles.WindowWideStyleSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ApplicationWideStyleSample" Height="200" Width="300">
    <StackPanel Margin="10">
        <TextBlock>Header 1</TextBlock>
        <TextBlock>Header 2</TextBlock>
        <TextBlock Foreground="Blue">Header 3</TextBlock>
    </StackPanel>
</Window>

Explicitly using styles

You have a lot of control over how and where to apply styling to your controls, from local styles and right up to the application-wide styles, that can help you get a consistent look all over your application, but so far, all of our styles have targeted a specific control type, and then ALL of these controls have used it. This doesn't have to be the case though.

By setting the x:Key property on a style, you are telling WPF that you only want to use this style when you explicitly reference it on a specific control. Let's try an example where this is the case:

<Window x:Class="WpfTutorialSamples.Styles.ExplicitStyleSample"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExplicitStyleSample" Height="150" Width="300">
    <Window.Resources>
        <Style x:Key="HeaderStyle" TargetType="TextBlock">
            <Setter Property="Foreground" Value="Gray" />
            <Setter Property="FontSize" Value="24" />
        </Style>
    </Window.Resources>
    <StackPanel Margin="10">
        <TextBlock>Header 1</TextBlock>
        <TextBlock Style="{StaticResource HeaderStyle}">Header 2</TextBlock>
        <TextBlock>Header 3</TextBlock>
    </StackPanel>
</Window>

Notice how even though the TargetType is set to TextBlock, and the style is defined for the entire window, only the TextBlock in the middle, where I explicitly reference the HeaderStyle style, uses the style. This allows you to define styles that target a specific control type, but only use it in the places where you need it.

Summary

WPF styling allows you to easily re-use a certain look for your controls all over the application. Using the x:Key property, you can decide whether a style should be explicitly referenced to take effect, or if it should target all controls no matter what.


This article has been fully translated into the following languages: Is your preferred language not on the list? Click here to help us translate this article into your language!