【msdn wpf forum翻译】TextBlock等类型的默认样式(implicit style)为何有时不起作用?

原文链接:http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/148e95c6-6fb5-4399-8a56-41d0e0a72f1b

疑问:
以下代码定义了一个TextBlock的默认样式:
        <Style TargetType="{x:Type TextBlock}">
            
<Style.Triggers>
                
<Trigger Property="Text" Value="">
                    
<Setter Property="Visibility" Value="Collapsed"/>
                
</Trigger>
            
</Style.Triggers>
        
</Style>
以下是TreeView的一个 HierarchicalDataTemplate 的定义:
            <HierarchicalDataTemplate DataType="XYZ" ItemsSource ="{Binding}">
                
<Grid x:Uid="Grid_7" Width="Auto" Height="Auto">
                    
<Grid.ColumnDefinitions>
                        
<ColumnDefinition/>
                        
<ColumnDefinition/>
                        
<ColumnDefinition/>
                        
<ColumnDefinition/>
                    
</Grid.ColumnDefinitions>
                    
<Grid.RowDefinitions>
                        
<RowDefinition/>
                    
</Grid.RowDefinitions>
                    
                    
<Image  Grid.Column="0" Grid.Row="0" Margin="5,0,0,0"/>
                    
<TextBlock  Grid.Column="1" Grid.Row="0" Padding="5,0,0,0"/>
                    
<TextBlock  Grid.Column="2" Grid.Row="0" Foreground="Blue"Padding="5,0,0,0"/>
                    
<TextBlock  Grid.Column="3" Grid.Row="0" Foreground="Red"Padding="5,0,0,0"/>                   
                
</Grid>
            
</HierarchicalDataTemplate>
之后,就算我们把 TextBlock的默认样式加到<TreeView.Resources> 之中,TextBlock也不会像预期的那样(预期:如果为空串时 Visibility == Collapsed)。
Johnny Q. 回答:
这个行为“by design”,简而言之,当一个直接继承自 FrameworkElement 的对象在一个 FrameworkTemplate 之中时,默认样式不起作用(当该样式定义在 FrameworkTemplate 之外的逻辑树的祖先节点时)。

This is by design, as far as I know (if it's good or bad, that can be debatable; maybe things will change in future releases). For short, default styles do not work with objects directly derived from FrameworkElement, when placed inside FrameworkTemplate. See also http://shevaspace.blogspot.com/2007/03/wtf-of-wpf-part-one-templating-styling.html


注:
http://shevaspace.blogspot.com/2007/03/wtf-of-wpf-part-one-templating-styling.html (需FQ)中更为详细的描述了这个问题,给出了一个可以在 xamlpad 中演示的例子,并指出了这个行为是在 FrameworkElement.FindImplicitStyleResource() 函数中进行限制的。 以下先给出链接中的例子:
Code


之后,我们打开 MS 发布的 wpf 的源代码(.net 3.0版)找到 FrameworkElement.FindImplicitStyleResource() 函数(注意参数重载,第一个参数为FrameworkElement的才是我们要找的):

Code


在这里我们只需要关注两个地方:
1. 第4、5行的注释。
2. 第18-24行的注释及代码。
可知,如果FrameworkElement的 非Control子类 的对象,其默认样式的搜索边界是其TemplateParent,而MS是出于性能优化的角度,进行这样的设计的。

为什么值得这样设计呢?以下是我的分析、推测:
我们知道,Control 类有 Template 属性,依照上面的结论, ControlTemplate 中 FrameworkElement 的非Control子类 的对象,其默认样式的搜索边界就是 其 TemplateParent,这样设计之后,搜索默认样式的速度就会被加快(可通过使用Reflector+Reflector's baml viewer add-in 查看 PresentationFramework.Aero.dll 中的 themes/aero.normalcolor.baml 来查看 Aero 主题的控件的默认Template)。

回到篇首提到的那个问题,我们可知,可通过在HierarchicalDataTemplate 的 Grid.Resource 中定义 TextBlock 的默认样式来实现提问者想要的功能。

原文地址:https://www.cnblogs.com/caoyang/p/1536297.html