有用的东西
我需要设置某种类型的控件,这些控件是StackPanel的子控件。我正在使用:
<StackPanel>
<StackPanel.Resources>
<Style TargetType="{x:Type TextBlock}">...</Style>
</StackPanel.Resources>
<TextBlock ...>
...
</StackPanel>
这很好用!每个TextBlock都会查看它的父级(StackPanel)的资源,以了解它应该如何设置样式。将TextBlock嵌套到StackPanel上的距离无关紧要...如果它在其直接父级中找不到样式,它将查看其父级的父级,依此类推,直到找到某些东西(在这种情况下) ,()中定义的风格。
不起作用的东西
当我在具有模板的ContentControl中嵌套TextBlock时遇到了问题(请参阅下面的代码)。 ControlTemplate似乎破坏了TextBlock从父母,祖父母那里检索其风格的方式......
ControlTemplate的使用有效地似乎消除了TextBlock找到其合法风格的手段(StackPanel.Resources中的风格)。遇到ControlTemplate时,它会停止在树中的资源中查找其样式,而是默认使用Application本身的MergedDictionaries中的样式。
<StackPanel Orientation="Vertical" Background="LightGray">
<StackPanel.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Green" />
</Style>
</StackPanel.Resources>
<TextBlock Text="plain and simple in stackpanel, green" />
<ContentControl>
<TextBlock Text="inside ContentControl, still green" />
</ContentControl>
<ContentControl>
<ContentControl.Template>
<ControlTemplate TargetType="{x:Type ContentControl}">
<StackPanel Orientation="Vertical">
<ContentPresenter />
<TextBlock Text="how come this one - placed in the template - is not green?" />
</StackPanel>
</ControlTemplate>
</ContentControl.Template>
<TextBlock Text="inside ContentControl with a template, this one is green as well" />
</ContentControl>
</StackPanel>
有没有办法 - 除了将StackPanel.Resources中的Style复制到ControlTemplate.Resources之外 - 使ControlTemplate中的TextBlock找到定义的样式?
...谢谢
答案 0 :(得分:22)
WPF认为ControlTemplates
是边界,并且不会在模板中应用隐式样式(没有x:Key
的样式)。
但是这条规则有一个例外:从Control
继承的任何内容都将应用隐式样式。
因此,您可以使用Label
而不是TextBlock
,它会应用在XAML层次结构中进一步定义的隐式样式,但是TextBlock
继承自FrameworkElement
而不是Control
,它不会自动应用隐式样式,您必须手动添加它。
我最常见的解决方法是在ControlTemplate.Resources
中添加一个隐式样式BasedOn
现有的隐式TextBlock
样式
<ControlTemplate.Resources>
<Style TargetType="{x:Type TextBlock}"
BasedOn="{StaticResource {x:Type TextBlock}}" />
<ControlTemplate.Resources>
解决这个问题的其他常见方法是:
将隐式样式放在<Application.Resources>
中。无论模板边界如何,此处放置的样式都将适用于整个应用程序。但要小心,因为它会将样式应用于其他控件中的TextBlocks
,如Buttons或ComboBoxes
<Application.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Green" />
</Style>
</Application.Resources>
使用Label
代替TextBlock
,因为它是从Control
继承的,因此将应用在ControlTemplate
为基本样式指定x:Key
,并将其用作TextBlock
内隐式ControlTemplate
样式的基本样式。它与顶级解决方案几乎相同,但它用于具有x:Key
属性的基本样式
<Style x:Key="BaseTextBlockStyle" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Green" />
</Style>
...
<ControlTemplate.Resources>
<Style TargetType="{x:Type TextBlock}"
BasedOn="{StaticResource BaseTextBlockStyle}" />
<ControlTemplate.Resources>