Blog.Xinxing

Articles about tech, physics, and everything else related to life!

WPF default style

How to use a WPF Style

Every WPF FrameworkElement has a Style property, which you can use to customize your WPF controls. Create a style the control’s Style property, and you can set any DependencyProperties of that control with Setters or Triggers in the Style:

<TextBlock Text="Welcome to my blog!" >
    <TextBlock.Style>
        <Style>
            <Setter Property="Background" Value="Yellow" />
        </Style>
    </TextBlock.Style>
</TextBlock>

What if we want to reuse the Style

To reuse a Style, we often define the style as a resource in ResourceDictionary and set target control type. Note that the Style will be applied to any instances of that control type by default:

<ResourceDictionary>
    <Style TargetType="{x:Type TextBlock}>
        <Setter Property="Background" Value="Yellow" />
    </Style>
</ResourceDictionary>
<TextBlock Text="Welcome to my blog!" />

What if the control has another Style defined?

For example:

<ResourceDictionary>
    <Style TargetType="{x:Type TextBlock}>
        <Setter Property="Background" Value="Yellow" />
    </Style>
</ResourceDictionary>
<TextBlock Text="Welcome to my blog!">
    <TextBlock.Style>
        <Style>
            <Setter Property="Foreground" Value="Red" />
        </Style>
    </TextBlock.Style>
</TextBlock>


Clearly, the default style was overwriten. Controls could not have more than one Style.

What if we want to apply both styles to the TextBlock?

Simple answer: use Style.BasedOn property for style derivation!
To do this, we add a key “TextBlockBaseStyle” for the base style so that it could be easy referred to:

<ResourceDictionary>
    <Style x:Key="TextBlockBaseStyle" TargetType="{x:Type TextBlock}>
        <Setter Property="Background" Value="Yellow" />
    </Style>
</ResourceDictionary>
<TextBlock Text="Welcome to my blog!">
    <TextBlock.Style>
        <Style BasedOn="{StaticResource TextBlockBaseStyle}">
            <Setter Property="Foreground" Value="Red" />
        </Style>
    </TextBlock.Style>
</TextBlock>

Great! Things work! However, if you have another TextBlock instance defined in the same xaml file, it might lose its default Style:

<ResourceDictionary>
    <Style x:Key="TextBlockBaseStyle" TargetType="{x:Type TextBlock}>
        <Setter Property="Background" Value="Yellow" />
    </Style>
</ResourceDictionary>
<TextBlock Text="Feel free to bookmark our site!" />

Notice that the “default” Style targetting TextBlock was not applied to this TextBlock. Why???

Why your control is not picking up “default” Style

This is because, ResourceDictionary is a real key-value dictionary. If no key is specified for a Style, the TargetType will be used as the key. If a control has no Style set, WPF will check the control type as a key in the dictionary, and find the Style to be applied on the control. That is why a Style without key explicitly set would serve as “default” Style that applied for a control type.
However, if the key was set, TargetType would no longer be used as a key for that Style, so the Style would no longer be the default one.
As a result, to apply our default Style to the second TextBlock, we need to remove the key. But if the key is absent, how do we refer to it in the first TextBlock’s Style?

How to refer to a default Style

Use the type as key:

<ResourceDictionary>
    <Style TargetType="{x:Type TextBlock}>
        <Setter Property="Background" Value="Yellow" />
    </Style>
</ResourceDictionary>
<TextBlock Text="Welcome to my blog!">
    <TextBlock.Style>
        <Style BasedOn="{StaticResource {x:Type TextBlock}}">
            <Setter Property="Foreground" Value="Red" />
        </Style>
    </TextBlock.Style>
</TextBlock>
<TextBlock Text="Feel free to bookmark our site!" />


Now both TextBlocks works as expected!

Note that the same with the code in Style.TargetType, code "{x:Type TextBlock}" in Style.BasedOn is used to create a type object. And that is used as a key to search for the Style in ResourceDictionary.

Tagged , , , , , , , , , ,

Leave a Reply

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