Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF override style in merged dictionary

In my dictionary file I have

<Style TargetType="{x:Type Label}" BasedOn="{StaticResource {x:Type Label}}">
    <Setter Property="Foreground" Value="White" />
    <Setter Property="Background" Value="Black" />
</Style>

In my Window xaml file I have

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/XXX;component/XXX.xaml"/>
            </ResourceDictionary.MergedDictionaries>

            <Style TargetType="Label" BasedOn="{StaticResource {x:Type Label}}">
                <Setter Property="FontSize" Value="20"/>
                <Setter Property="VerticalAlignment" Value="Center"/>
            </Style>
        </ResourceDictionary>
    </Window.Resources>

In the designer I can see the label has black background and white foreground but during run time it has the default black foreground and transparent background. It is pretty obvious that I want to inherit the dictionary style and it is not working. Any thing I did wrong in there? I am Using VS 2013 and .NET 4.5

Edit: If I remove the style inside Windows.Resources then the dictionary style will get applied. If I move the style from Windows Resource to the StackPanel.Resource which contains some labels, then the inheritance works fine

like image 443
Steve Avatar asked Sep 15 '14 23:09

Steve


1 Answers

According to MSDN, Merged Resource Dictionaries:

If a key is defined in the primary dictionary and also in a dictionary that was merged, then the resource that is returned will come from the primary dictionary.

According to this rule, your second style is found first. That style then references a style with the same {x:Type Label} key. For some reason, that resolves to null. Inspecting the first style however shows that its BasedOn reference got resolved to the default Label style, as expected. The same happens when both styles are given the same explicit key. Everything works as expected when they are given different keys, however.

My guess is that the second style shadows the first one. Perhaps the BasedOn reference is resolved to the style itself, but in order to prevent cyclic dependencies it's set to null instead.

Personally I would use explicit keys. For styles that need to be applied to all elements of a certain type, but that still need to be overridden in some cases, I would split things up into two styles:

// The actual style, with all its setters, is given a descriptive name:
<Style x:Key="DescriptiveName" TargetType="Label" BasedOn="{StaticResource {x:Type Label}}">
    // Setters go here
</Style>

// A 'dummy' style that references the above style.
// Its sole purpose is to apply the style to all elements of the target type.
<Style TargetType="Label" BasedOn="{StaticResource DescriptiveName}" />

When you need to override the style, you can unambiguously reference it by it's name:

<Style TargetType="Label" BasedOn="{StaticResource DescriptiveName}">
    // Overriding setters go here
</Style>
like image 69
Pieter Witvoet Avatar answered Nov 03 '22 23:11

Pieter Witvoet