为什么我的风格没有被应用? [英] Why doesn't my style get applied?
问题描述
我的问题与这篇文章中的问题相同.但是,由于这篇旧文章四年来一直没有答案,所以我想也许有一些新的见解可以解释为什么它不像预期的那样起作用.
my question is the same as in this post. But since this old post is without an answer for four years I thought maybe there are new insights on why this is not working like it's supposed to be.
在我的窗口资源中,我为TextBlock
定义了一种简单的样式.样式没有x:Key
属性,因此应该将其应用于窗口中所有不具有自己样式的TextBlock
控件.
In my window resources I define a simple style for a TextBlock
. The style doesn't have a x:Key
attribute, so it's supposed to be applied to all TextBlock
controls within my window which doesn't have a style of their own.
然后我创建一个ListView
,将GridView
定义为其视图. ListView
定义了四个列,两个列定义为包含TextBlock
的显式CellTemplate
,而两个列定义为不包含CellTemplate
的显式.
Then I create a ListView
with a GridView
defined as its view. The ListView
has four colums defined, two columns are defined with an explicit CellTemplate
containing a TextBlock
and two columns are defined without an explicit CellTemplate
.
这是我完整的XAML代码(问题在代码下方):
Here's my complete XAML-code (the question follows under the code):
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" SizeToContent="WidthAndHeight">
<Window.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
<Setter Property="Background" Value="Aqua" />
</Style>
<Style x:Key="ListViewItemStyle" TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</Window.Resources>
<ListView ItemContainerStyle="{StaticResource ListViewItemStyle}">
<ListView.View>
<GridView>
<GridViewColumn Header="Bottom" Width="50" DisplayMemberBinding="{Binding Bottom}" />
<GridViewColumn Header="Left" Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Left}" TextAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Right" Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Right}" TextAlignment="Right" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Top" Width="50" DisplayMemberBinding="{Binding Top}" />
</GridView>
</ListView.View>
<ListView.Items>
<Thickness>1,2,3,4</Thickness>
<Thickness>5,6,7,8</Thickness>
<Thickness>9,10</Thickness>
</ListView.Items>
</ListView>
</Window>
如果运行此代码,我会看到应该应用于所有TextBlock
控件的TextBlock
样式仅在没有显式CellTemplate
的列中处于活动状态.
If I run this code, I can see, that my TextBlock
style, that is supposed to be applied to all TextBlock
controls, is only active in the columns that don't have an explicit CellTemplate
.
那是为什么?
当我检查视觉树时,我看到,工作列(没有 和CellTemplate
的工作列)是由TextBlock
组成的,并且将我的样式应用于该列,不起作用(带有和的CellTemplate
)是由内部带有TextBlock
的ContentPresenter
组成的,但是TextBlock
根本没有样式.
When I inspect the visual tree I can see, that the working columns (the ones without a CellTemplate
) are made of a TextBlock
with my style applied to it, while the columns, which don't work (the ones with a CellTemplate
) are made of a ContentPresenter
with a TextBlock
inside, but the TextBlock
has no style at all.
推荐答案
此行为实际上是设计使然. 此链接描述了正在发生的事情.早在2006年10月,Microsoft Connect上也有一个错误报告.遗憾的是,给定链接中指向该错误报告的原始链接不再起作用.
This behavior is actually by design. This link describes what is going on. There was also a bug report on Microsoft Connect back in October 2006. Unfortunately the original link to the bug report in the given link does not work anymore.
在这里,我列举了Connect的错误报告的答案,以防将来给定的链接断开.
Here I'm reciting the answer to the bug report from Connect in case the given link goes down in future.
此行为是按设计",这就是原因.模板被视为封装边界.这些模板产生的元素都在此边界之内.对于具有匹配TargetType的样式的查找将在此边界处停止.因此,通过模板生成的repro中的TextBlock不会拾取有问题的样式.而在模板外部定义的TextBlock可以. 解决此问题的一种方法是为样式指定一个明确的名称,并通过此名称在模板中的TextBlock上引用该样式.
This behavior is 'By Design' and this is why. Templates are viewed as an encapsulation boundary. Elements produced by these templates fall within this boundary. And lookup for a style with a matching TargetType stops at this boundary. Hence the TextBlock in the repro which is produced through a template does not pick up the Style in question. Whereas the TextBlock defined outside the template does. One way to work around this problem is to give an explicit name to the Style and reference the style by this name on the TextBlock within the template.
您看到他们已经为您的问题提供了解决方法.他们声明您应该在Window.Resources
中为您的TextBlock
样式命名,并在模板中引用该样式.
You see that they already provided a workaround for your issue. They state that you should give your TextBlock
style in the Window.Resources
a name and reference the style in the template.
我认为这不是您真正想要的,因为在那种情况下,样式不会自动应用于所有TextBlocks(在DataTemplate之外).因此,不必在Windows.Resources
中为样式指定一个明确的名称,而是可以在引用样式时在BasedOn
属性中进行一些操作.您无需指定样式的名称,而是指定类似的类型.
I think this is not what you actually want, because in that case the style doesn't automatically get applied to all TextBlocks (outside the DataTemplate). For that reason, instead of giving the style in Windows.Resources
an explicit name, you can do a little trick in your BasedOn
property when referencing the style. Instead of specifying the name of the style, you specify the type like this.
<GridViewColumn Header="Left" Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<DataTemplate.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}" />
</DataTemplate.Resources>
<TextBlock Text="{Binding Left}" TextAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
使用这种方法,您仍然具有不为样式指定名称的优点,并且该样式将应用于所有TextBlock.
With that approach, you still have the advantage of not specifying a name for your style and the style gets applied to all TextBlocks.
作为参考,整个Window XAML看起来像这样.现在,GridView
中的所有列都具有相同的样式.
For reference, the whole Window XAML looks like this. Now, all columns in the GridView
have the same style.
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" SizeToContent="WidthAndHeight">
<Window.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
<Setter Property="Background" Value="Aqua" />
</Style>
<Style x:Key="ListViewItemStyle" TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</Window.Resources>
<ListView ItemContainerStyle="{StaticResource ListViewItemStyle}">
<ListView.View>
<GridView>
<GridViewColumn Header="Bottom" Width="50" DisplayMemberBinding="{Binding Bottom}" />
<GridViewColumn Header="Left" Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<DataTemplate.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}" />
</DataTemplate.Resources>
<TextBlock Text="{Binding Left}" TextAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Right" Width="50">
<GridViewColumn.CellTemplate>
<DataTemplate>
<DataTemplate.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}" />
</DataTemplate.Resources>
<TextBlock Text="{Binding Right}" TextAlignment="Right" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn Header="Top" Width="50" DisplayMemberBinding="{Binding Top}" />
</GridView>
</ListView.View>
<ListView.Items>
<Thickness>1,2,3,4</Thickness>
<Thickness>5,6,7,8</Thickness>
<Thickness>9,10</Thickness>
</ListView.Items>
</ListView>
</Window>
这篇关于为什么我的风格没有被应用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!