• 正确理解WPF中的TemplatedParent (转贴)


    http://blog.csdn.net/idebian/article/details/8761388

    (注:Logical Tree中文称为逻辑树,Visual Tree中文称为可视化树或者视觉树,由于名称不是很统一,文中统一用英文名称代表两个概念,况且VisualTreeHelper和LogicalTreeHelper也是WPF中提供的类名称)

    众所周知WPF中的Logical Tree是逻辑上定义的元素层次树,而实际上显示在屏幕上的元素层次树是Visual Tree,Visual Tree是Logical Tree节点扩充后的的产物。因此从Visual Tree的角度上看(Visual Tree当然是完整的一个),Logical Tree被分割成一段一段的,而这些段与段的连接点,就是和TemplatedParent有关。

    这个概念在WPF类模型中是FrameworkElement.TemplatedParent属性。WPF中的模板(数据模板和控件模板)都可以扩展Logical Tree,那么模板所修饰的对象就是模板中元素的TemplatedParent,此时模板元素和修饰对象都会出现在Visual Tree中,但模板元素肯定不属于被修饰元素的Logical Tree,但是模板有自己的Logical Tree,两个Logical Tree是分开的,但是通过TemplatedParent,两者之间又有联系。

    说再多不如实例形象,来看下面示例代码:

    这是一个简单的ContentControl,它的Content是一个按钮,然后定义了控件模板和数据模板,代码中一些关键元素有Name属性,我们在后续讨论就以Name属性的值来引用这些元素

    <ContentControl Name="contentControl">  
      
                  
      
        <!-- 控件模板 -->  
      
        <ContentControl.Template>  
      
            <ControlTemplate TargetType="ContentControl">  
      
                <Border Name="bd1">  
      
                    <ContentPresenter Name="cp1" ContentSource="Content"/>  
      
                </Border>  
      
             </ControlTemplate>  
      
         </ContentControl.Template>  
      
                  
      
         <!-- 数据模板 -->  
      
         <ContentControl.ContentTemplate>  
      
             <DataTemplate>  
      
                 <Border Name="bd2">  
      
                     <ContentPresenter Name="cp2" Content="{Binding}" />  
      
                 </Border>  
      
              </DataTemplate>  
      
          </ContentControl.ContentTemplate>  
      
                  
      
          <!-- 逻辑孩子 -->  
      
          <Button Name="btn">按钮</Button>  
      
    </ContentControl> 
    

      这个ContentControl的Visual Tree如下图:

    图中相同颜色的节点代表它们属于同一个Logical Tree,可以看出来,整个Visual Tree分成多个Logical Tree,而这些Logical Tree是分开的,比如上面代码中的两个Border(名称是bd1和bd2),它们的Parent属性的值都是null,即没有逻辑父节点。但是这些逻辑树通过TemplatedParent是互相有联系的。比如控件模板中的元素的TemplatedParent指代最上方的ContentControl,而数据模板元素的TemplatedParent则是控件模板内的ContentPresenter元素。

    通过代码也可以验证这些:(bd1, bd2, cp1, cp2分别代表控件模板和数据模板中的Border和ContentPresenter)

        private void Button_Click(object sender, RoutedEventArgs e)  
          
        {  
          
            var bd1 = (Border)contentControl.Template.FindName("bd1", contentControl);  
          
            var cp1 = (ContentPresenter)contentControl.Template.FindName("cp1", contentControl);  
          
            var bd2 = (Border)contentControl.ContentTemplate.FindName("bd2", cp1);  
          
            var cp2 = (ContentPresenter)contentControl.ContentTemplate.FindName("cp2", cp1);  
          
           
          
            PrintInfo(bd1, cp1, bd2, cp2, btn);  
          
        }  
          
           
          
        void PrintInfo(params FrameworkElement[] eles)  
          
        {  
          
            string s = "";  
          
            foreach (var ele in eles)  
          
                s += String.Format("{2}
    Parent: {0}
    TemplatedParent: {1}
    
    ", ele.Parent, ele.TemplatedParent, ele.Name);  
          
            MessageBox.Show(s);  
          
        }  
  • 相关阅读:
    ExtJS小技巧
    Oracle 表的行数、表占用空间大小,列的非空行数、列占用空间大小 查询
    NPM 私服
    IDEA 不编译java以外的文件
    SQL 引号中的问号在PrepareStatement 中不被看作是占位符
    Chrome 浏览器自动填表呈现淡黄色解决
    批量删除Maven 仓库未下载成功.lastupdate 的文件
    Oracle 11g 监听很慢,由于监听日志文件太大引起的问题(Windows 下)
    Hibernate 自动更新表出错 建表或添加列,提示标识符无效
    Hibernate 自动更新表出错 More than one table found in namespace
  • 原文地址:https://www.cnblogs.com/macleo/p/7429108.html
Copyright © 2020-2023  润新知