WPF覆盖合并字典中的样式

时间:2014-09-15 23:30:39

标签: c# wpf resourcedictionary

在我的词典文件中,我有

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

在我的Window xaml文件中,我有

    <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>

在设计师中我可以看到标签有黑色背景和白色前景,但在运行时它有默认的黑色前景和透明背景。很明显,我想继承字典样式,但它不起作用。我在那里做错了什么?我正在使用VS 2013和.NET 4.5

编辑: 如果我删除Windows.Resources中的样式,那么将应用字典样式。如果我将样式从Windows资源移动到包含一些标签的StackPanel.Resource,那么继承可以正常工作

1 个答案:

答案 0 :(得分:5)

根据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.

根据此规则,首先找到您的第二种风格。然后,该样式引用具有相同{x:Type Label}键的样式。出于某种原因,这将解析为null。但是,检查第一个样式会显示其BasedOn引用已按预期解析为默认的Label样式。当两个样式都被赋予相同的显式键时,会发生同样的情况。但是,当它们被赋予不同的键时,一切都按预期工作。

我的猜测是第二种风格影响第一种风格。也许BasedOn引用被解析为样式本身,但为了防止循环依赖,它被设置为null。

我个人会使用显式键。对于需要应用于某种类型的所有元素但在某些情况下仍需要覆盖的样式,我会将其分为两种样式:

// 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}" />

当您需要覆盖样式时,您可以通过它的名称明确地引用它:

<Style TargetType="Label" BasedOn="{StaticResource DescriptiveName}">
    // Overriding setters go here
</Style>