wpf 为 ContentPresenter 中的所有元素设置样式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20116418/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Set Style for all elements inside ContentPresenter
提问by user1706449
I overrided the template of wpf expander. The header has ContentPresenter
我覆盖了 wpf 扩展器的模板。标题有 ContentPresenter
<ContentPresenter x:Name="HeaderContent"
Grid.Column="1"
Margin="0,0,4,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
RecognizesAccessKey="True"
SnapsToDevicePixels="True"
>
<ContentPresenter.Resources>
<Style BasedOn="{StaticResource Expanderheader-Naming}"
TargetType="{x:Type TextBlock}" />
</ContentPresenter.Resources>
</ContentPresenter>
Where I tried to add my style for all TextBlocks inside. My style works if I set the header as a property:
我试图为里面的所有 TextBlock 添加我的样式。如果我将标题设置为属性,则我的样式有效:
<Expander Header="HelloWorld">
But it doesn't when I try to set it in the other manner.
但是当我尝试以另一种方式设置它时,它不会。
<Expander>
<Expander.Header>
<Grid x:Name="MyGrid">
<TextBlock>Hello Man</TextBlock>
</Grid>
</Expander.Header>
</Expander>
How to set this style for any TextBlocks inside the ContentPresenter?
如何为 ContentPresenter 中的任何 TextBlocks 设置此样式?
回答by dev hedgehog
You ran into typical style inheritance issue in wpf.
您在 wpf 中遇到了典型的样式继承问题。
A control looks for its style at the point when it is being initalized. The way the controls look for their style is by moving upwards in logical tree and asking the logical parent if there is appropriate style for them stored in parent's resources dictionary.
控件在初始化时查找其样式。控件查找其样式的方式是在逻辑树中向上移动并询问逻辑父级是否有适合它们存储在父级资源字典中的样式。
To explain to you what you doing wrong in your example lets think like this.
为了向您解释您在示例中做错了什么,让我们这样想。
In first example the header properly is just storing "HelloWorld" and later when control is being initalized "HelloWorld" will be injected into ContentPresenter. This approach provides "HelloWorld" with ContentPresenter being it logical parent and so the style is applied properly since the style can be found.
在第一个示例中,标头正确地只是存储“HelloWorld”,稍后在初始化控件时“HelloWorld”将被注入到 ContentPresenter 中。这种方法为“HelloWorld”提供了 ContentPresenter 作为其逻辑父项,因此可以正确应用样式,因为可以找到样式。
In second example you create a Grid and inside that Grid you have a TextBlock.
在第二个示例中,您创建了一个网格,并且在该网格内有一个 TextBlock。
At point of control initalization the logical parent of your TextBlock is Grid and futhermore Grid's logical parent is Expander itself. When looking for style for TextBlock the WPF will ask TextBlock's logical parent if it has a proper style in its resources for the TextBlock and the answer will be NO. There is no proper style for the TextBlock inside Grid.Resources and there is no proper style for the TextBlock inside Expander.Resources.
在控制初始化时,TextBlock 的逻辑父级是 Grid,而且 Grid 的逻辑父级是 Expander 本身。在为 TextBlock 寻找样式时,WPF 将询问 TextBlock 的逻辑父级是否在 TextBlock 的资源中具有正确的样式,答案是否定的。Grid.Resources 中的 TextBlock 没有合适的样式,Expander.Resources 中的 TextBlock 没有合适的样式。
The proper style would be inside ContentPresenter just in this case the ContentPresenter is not part of logical tree.
正确的样式应该在 ContentPresenter 中,只是在这种情况下 ContentPresenter 不是逻辑树的一部分。
That is how you lose the style in your second example.
这就是你在第二个例子中失去风格的方式。
In order to fix this I suggest you to stick to first example or to change where the style is being stored to. Usually all styles shall be stored inside Window.Resources.
为了解决这个问题,我建议您坚持使用第一个示例或更改样式的存储位置。通常所有样式都应存储在 Window.Resources 中。
EDIT 2Take a look at this example carefully:
编辑 2仔细看看这个例子:
<Window.Resources>
<Style x:Key="textBlockStyle" TargetType="TextBlock">
<Setter Property="Background" Value="Blue"/>
</Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter>
<ContentPresenter.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource textBlockStyle}"/>
</ContentPresenter.Resources>
</ContentPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<StackPanel>
<Button Content="Yay, it worked!" />
<Button>
<Grid>
<TextBox Text="It doesn't work this way!"/>
</Grid>
</Button>
<Button>
<Grid>
<Grid.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource textBlockStyle}"></Style>
</Grid.Resources>
<TextBlock Text="Yay it works again! Woop Woop"/>
</Grid>
</Button>
</StackPanel>

