为什么Listbox中的DataTemplate不使用Windows.Resources样式?

4

我有以下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,但是在窗口的其他 TextBlock 上应用了该样式。
如果我将 Style 复制并在 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>

然后它就可以工作了。你有什么想法为什么需要重复样式?

提前感谢。

3个回答

4
隐式样式仅适用于从 "System.Windows.Controls.Control" 继承的类型的模板,而由于 "TextBlock" 直接继承自 "System.Windows.FrameworkElement",因此它不起作用。您必须为您的样式指定 "x:Key" 并明确使用它,或者在 "Application.Resources" 中声明您的样式,但这样将应用于所有的 "TextBlocks",也就是说,基本上应用于整个应用程序中显示的每一位文本。

иҝҷдёҚжҳҜзңҹзҡ„гҖӮйҡҗејҸж ·ејҸеҸӘйңҖиҰҒиҰҶзӣ–DefaultStyleKeyеұһжҖ§пјҢиҖҢTextBlockе·Із»Ҹе®һзҺ°дәҶе®ғгҖӮ - Eli Arbel
覆盖DefaultStyleKey并在您的Window中编写隐式样式是不同的。基本上,当非System.Windows.Controls.Control元素的样式被评估时,它不会超出该模板以检查其他元素资源,而是直接转到Application.Resources,然后是DefaultStyleKey - dkozl
你说得对,我没有注意到你写的是它只在模板内才成立。抱歉 :) - Eli Arbel

3
这是 WPF 的一种怪癖。当控件不从 Control 继承,而是直接从 FrameworkElement 继承时,在模板中进行隐式样式查找时会直接跳过到应用程序资源。如果将样式放在应用程序资源 (App.xaml) 中,则可以正常工作。
另外,您可以使用命名的资源和 BasedOn 引用它:
    <DataTemplate.Resources>
        <Style TargetType="TextBlock" BasedOn="{StaticResource MyTextStyle}" />
    </DataTemplate.Resources>

2
请看《DataTemplate和Style的混淆》
我在2006年10月将此问题发布到Connect上。
“这种行为是按设计来的。模板被视为封装边界,由这些模板生成的元素位于此边界内。具有匹配TargetType的样式的查找在此边界处停止。因此,通过模板生成的TextBlock无法获取所需的样式,而模板外定义的TextBlock可以。
解决此问题的一种方法是给样式命名,并在模板中的TextBlock上引用这个名称。”

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接