WPF ControlTemplate 打破样式 [英] WPF ControlTemplate breaks style

查看:27
本文介绍了WPF ControlTemplate 打破样式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有用的东西

我需要设置作为 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 时,它​​停止在树上的资源中寻找它的样式,而是默认为应用程序本身的 MergedDictionaries 中的样式.

<StackPanel.Resources><Style TargetType="{x:Type TextBlock}"><Setter Property="Foreground" Value="Green"/></风格></StackPanel.Resources><TextBlock Text="plain and simple in stackpanel, green"/><内容控制><TextBlock Text="在 ContentControl 里面,仍然是绿色的"/></内容控制><内容控制><ContentControl.Template><ControlTemplate TargetType="{x:Type ContentControl}"><StackPanel Orientation="垂直"><ContentPresenter/><TextBlock Text="为什么这个——放在模板中——不是绿色的?/></StackPanel></控制模板></ContentControl.Template><TextBlock Text="在带有模板的 ContentControl 中,这个也是绿色的"/></内容控制></StackPanel>

除了将 StackPanel.Resources 中的 Style 复制到 ControlTemplate.Resources 之外,有没有办法让 ControlTemplate 中的 TextBlock 找到定义的样式?

谢谢...

解决方案

WPF 将 ControlTemplates 视为边界,并且不会应用隐式样式(没有 x:Key) 模板内.

但此规则有一个例外:从 Control 继承的任何内容都将应用隐式样式.

因此您可以使用 Label 而不是 TextBlock,它会应用在 XAML 层次结构中进一步定义的隐式样式,但是由于 TextBlock 继承自 FrameworkElement 而不是 Control,它不会自动应用隐式样式,您必须手动添加它.

我最常用的解决方法是在 ControlTemplate.Resources 中添加一个隐式样式,即 BasedOn 现有的隐式 TextBlock风格

 <Style TargetType="{x:Type TextBlock}"BasedOn="{StaticResource {x:Type TextBlock}}"/><ControlTemplate.Resources>

解决此问题的其他常见方法是:

  • 将隐式样式放在 中.放置在这里的样式将适用于您的整个应用程序,无论模板边界如何.不过要小心,因为它也会将样式应用于其他控件内部的 TextBlocks,例如按钮或组合框

    <Style TargetType="{x:Type TextBlock}"><Setter Property="Foreground" Value="Green"/></风格></Application.Resources>

  • 使用 Label 而不是 TextBlock 因为它继承自 Control,所以将应用在 之外定义的隐式样式>控制模板

  • 给基本样式一个 x:Key 并将其用作 ControlTemplate 内隐式 TextBlock 样式的基本样式.它与顶级解决方案几乎相同,但是它用于具有 x:Key 属性的基本样式