【问题标题】:Redefine datatemplate style重新定义数据模板样式
【发布时间】:2013-01-07 15:40:16
【问题描述】:

假设我在应用程序级别为 TextBlock 定义了一个样式,并且我还在应用程序级别为使用一些 TextBlocks 的“DataClass”定义了一个 DataTemplate。现在,在应用程序的某些子部分中,我想重新定义 TextBlock 的外观,我可以重新定义 TextBlock 的样式。

这里的问题是:如果在应用的这个子部分应用了DataTemplate,那么里面的所有TextBlocks仍然会使用应用级别的TextBlock样式(而不是我重新定义的版本)。有谁知道如何重新定义 DataTemplate 的样式?

【问题讨论】:

    标签: wpf styles datatemplate


    【解决方案1】:

    <Application.Resources> 中的样式适用于整个应用程序,并不总是遵循默认样式查找规则。

    通常,如果您不希望出现这种行为,请将样式放在 <Window.Resources> 中,这样它们将仅适用于您窗口内的对象,并且将使用正常的样式查找规则。

    默认情况下,样式不会跨控件/模板边界应用,除了用于继承自 Control 的对象的样式,这是大多数默认 WPF 控件,例如 Label 或 @987654327 @。

    因此,您可以在对象的.Resources 中设置任何Control 对象的样式,以使其应用于所有子对象:

    <UserControl.Resources>
        <Style TargetType="{x:Type Label}">
            <Setter Property="Foreground" Value="Red" />
        </Style>
    </UserControl.Resources>
    

    但TextBlock 继承自FrameworkElement 而不是Control,因此TextBlock 的样式不会跨模板边界应用。

    如果您确实希望将您的样式保留在 Application.Resources 中,那么您必须在创建 TextBlock 之前覆盖该样式中的属性,使其位于视觉树的下方,例如

    <UserControl x:Class="MyNamespace.MyDataTypeView"... >
        <UserControl.Resources>
            <Style TargetType="{x:Type TextBlock}">
                <Setter Property="Foreground" Value="Black" />
            </Style>
        </UserControl.Resources>
    
        <TextBlock Text="Test" />
    </UserControl>
    

    但是,此样式不会应用于 UserControl 中另一个控件内的对象,例如 ComboBox 内的 ComboBoxItems 文本

    在子控件中使用的TextBlock 将应用来自Application.Resources 的TextBlock 样式,但不会应用来自&lt;UserControl.Resources&gt; 的样式,因为Application.Resources 中定义的TextBlock 样式将跨越控件/模板边界,而定义的TextBlock 样式在任何其他X.Resources 不会。

    在这些特定情况下,您可能需要追踪x:Static 刷子键用于设置TextBlock.Text 颜色并覆盖您的ComboBox.Resources,例如

    (我可能在这里输入了错误的SystemColors 键)

    <ComboBox.Resources>
        <SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" />
    </ComboBox.Resources>
    

    【讨论】:

    • 好的,谢谢,关于边界的一些有趣信息。但是就像你说的控件中定义的样式不跨越 DataTemplate 边界,这实际上是我需要的。我想为某个控件中的所有子项重新定义数据模板中的属性(例如 BackGroundColor)。从你写的,我知道这可能是不可能的?
    • @user1896048 控件中定义的样式不会跨控件/模板边界继承除了,如果样式用于从Control 继承的对象,大多数控件做。例如,Label 继承自 Control,因此样式会在子标签中继承,但 TextBlock 不会因此样式不会被继承。您还可以创建通用样式,例如&lt;Style TargetType="{x:Type Control}"&gt;,并在那里设置Background 属性以使其适用于从Control 继承的所有对象,或者您可以覆盖SystemColor,例如我的上一个代码示例。
    • 实际上,这让我很吃惊。我认为样式是通过“范围”解决的,而不是继承(从父级传递给子级的继承),因为它们是资源……你知道任何官方消息来源讨论元素类型样式是如何解决的吗?
    • @user1896048 你说得对,我应该使用术语applied 而不是inherited。样式不是继承的,而是从应用程序的资源中查找并在需要时应用。我没有关于确切查找顺序的任何链接,但是 MSDN 上的依赖属性优先级页面上有 how the Style property is resolved 部分。
    猜你喜欢
    • 2010-12-27
    • 1970-01-01
    • 1970-01-01
    • 2012-09-21
    • 1970-01-01
    • 2014-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多