【问题标题】:Why a Listbox DataTemplate does not use the Windows.Resources styles?为什么 Listbox DataTemplate 不使用 Windows.Resources 样式?
【发布时间】:2013-10-03 19:59:54
【问题描述】:

我有以下 XAML(简体):

<Window ...

    <Window.Resources>
        <Style TargetType="{x:Type TextBlock}" >
            <Setter Property="FontSize" Value="28" />
            <Setter Property="Margin" Value="3" />
            <Setter Property="Foreground" Value="Green" />
        </Style>
    </Window.Resources>

    <StackPanel>

        <ListBox ItemsSource=...
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" >
                        <TextBlock Text="{Binding Index}" />
                        <TextBlock Text="-" />
                        <TextBlock Text="{Binding Hours, StringFormat={}{0:00}}" />
                        <TextBlock Text=":" />
                        <TextBlock Text="{Binding Minutes, StringFormat={}{0:00}}" />
                        <TextBlock Text=":" />
                        <TextBlock Text="{Binding Seconds, StringFormat={}{0:00}}" />
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

        ...

使用此代码,Window.Resources 中定义的样式不会应用于 DataTemplate 内的 TextBlock,而是应用于 Window 上的其他 TextBlock。

如果我复制样式并将其设置在 DataTemplate 资源中,如下所示:

        <DataTemplate.Resources>
            <Style TargetType="{x:Type TextBlock}" >
                <Setter Property="FontSize" Value="28" />
                <Setter Property="Margin" Value="3" />
                <Setter Property="Foreground" Value="Green" />
            </Style>
        </DataTemplate.Resources>

然后就可以了。知道为什么我需要复制样式吗?

提前致谢。

【问题讨论】:

    标签: c# wpf resources listbox datatemplate


    【解决方案1】:

    隐式Styles 仅适用于从System.Windows.Controls.Control 继承的类型,并且由于TextBlock 直接从System.Windows.FrameworkElement 继承,因此它不起作用。您必须提供您的样式x:Key 并明确使用它,或者在Application.Resources 中声明您的样式,但随后它将适用于所有TextBlocks,我的意思是基本上每个显示的文本位,在整个应用程序中

    【讨论】:

    • 这不是真的。隐式样式只要求您覆盖 DefaultStyleKey 属性,TextBlock 会这样做。
    • 覆盖DefaultStyleKey 并在Window 中编写隐式样式是不同的。基本上,当评估非System.Windows.Controls.Control 元素的样式时,它不会超出该模板来检查其他元素资源,而是直接转到Application.Resources,然后是DefaultStyleKey
    • 你说得对,我没有注意到你写道,它只在模板中是正确的。对不起:)
    【解决方案2】:

    这是一个 WPF 怪癖。当控件不是从Control 继承,而是直接从FrameworkElement 继承时,模板内的隐式样式查找会直接跳到应用程序资源。如果您将样式放在应用程序资源 (App.xaml) 中,它会起作用。

    或者,您可以使用命名资源和BasedOn 来引用它:

        <DataTemplate.Resources>
            <Style TargetType="TextBlock" BasedOn="{StaticResource MyTextStyle}" />
        </DataTemplate.Resources>
    

    【讨论】:

      【解决方案3】:

      请看DataTemplate and Style Confusion:

      我于 2006 年 10 月在 Connect 上将此作为“错误”发布。

      ...

      “这种行为是‘设计使然’,这就是原因。模板被视为封装边界。由这些模板生成的元素落在此边界内。查找具有匹配 TargetType 的样式会在此边界停止。因此通过模板生成的复制中的 TextBlock 不会选择有问题的样式。而在模板之外定义的 TextBlock 会。

      解决此问题的一种方法是为样式指定一个显式名称,并通过该名称在模板内的 TextBlock 上引用该样式。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-15
        • 2021-04-22
        • 1970-01-01
        相关资源
        最近更新 更多