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}\r\nParent: {0}\r\nTemplatedParent: {1}\r\n\r\n", ele.Parent, ele.TemplatedParent, ele.Name);  

        MessageBox.Show(s);  

    }  

正确理解WPF中的TemplatedParent (转贴)的更多相关文章

  1. 正确理解WPF中的TemplatedParent

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

  2. 理解WPF中的视觉树和逻辑树

    轉載地址:http://blog.csdn.net/changtianshuiyue/article/details/26981797 理解WPF中的视觉树和逻辑树  Understanding th ...

  3. WPF教程九:理解WPF中的对象资源

    在WPF中,所有继承自FrameworkElement的元素都包含一个Resources属性,这个属性就是我们这篇要讲的资源. 这一篇讲解的资源是不是上一篇的程序集资源(那个是在编译过程中打包到程序集 ...

  4. WPF教程六:理解WPF中的隧道路由和冒泡路由事件

    WPF中使用路由事件升级了传统应用开发中的事件,在WPF中使用路由事件能更好的处理事件相关的逻辑,我们从这篇开始整理事件的用法和什么是直接路由,什么是冒泡路由,以及什么是隧道路由. 事件最基本的用法 ...

  5. 如何正确理解正则表达式中的分隔符 \b

    前言:好久不见,博客园. 最近在学习研究regex,其中有个特迷惑自己的知识点是分隔符 ( word boundary) [\b] (注:为了方便,后文都以[]来包含字符,并不是reg规则里面的[] ...

  6. 2.如何正确理解古典概率中的条件概率《zobol的考研概率论教程》

    写本文主要是帮助粉丝理解考研中的古典概率-条件概率的具体定义. "B事件发生的条件下,A事件发生的概率"? "在A集合内有多少B的样本点"? "在B约 ...

  7. 正确理解JavaScript中的this关键字

    JavaScript有this关键字,this跟JavaScript的执行上下文密切相关,很多前端开发工程师至今对this关键字还是模棱两可,本文将结合代码讲解下JavaScript的this关键字. ...

  8. (转载)新手如何正确理解GitHub中“PR(pull request)”中的意思

    我从知乎看到的两个答案,分别从实际意义以及语言学角度告诉你改怎么理解PR,很简洁,这个理解非常棒,会解决新手刚看到PR(pull request)这个词时的困惑.   实际意义:   有一个仓库,叫R ...

  9. 正确处理WPF中Slider值改变事件的方式

    最近在用WPF数据绑定重写一下播放器项目时遇到的关于Slider的问题,在窗体透明度调节和播放进度调节上用了Slider控件.调节窗体透明度我是 这么想的:将窗体的Opacity属性的值与Slider ...

随机推荐

  1. 三种实现Ajax的方式

    本文主要是比较三种实现Ajax的方式 1. prototype.js 2. jquery1.3.2.min.js 3. json2.js Java代码 收藏代码 后台处理程序(Servlet),访问路 ...

  2. nginx 端口转发

    nginx 端口转发 默认nginx监听的端口是8080,想通过配置nginx访问80直接跳转到nginx,以下是配置方法: [root@localhost vhost]# cat tomcat.jo ...

  3. 小程序切换账户拉取仓库文件的appid提示

    小程序切换账户拉取仓库文件,拉取后appid会提示项目不是当前appid的项目,因为切换了账户,而每个小程序账户只有一个appid,所以会冲突 去project.config.json里吧appid改 ...

  4. codeforce 980B - Marlin(构造)

    Marlin time limit per test 1 second memory limit per test 256 megabytes input standard input output ...

  5. 权益保护-知识产权:知识产权(IP)百科

    ylbtech-权益保护-知识产权:知识产权(IP)百科 知识产权,也称其为“知识所属权”,指“权利人对其智力劳动所创作的成果和经营活动中的标记.信誉所依法享有的专有权利”,一般只在有限时间内有效.各 ...

  6. js 格式化相关的时间

    javascript Date format(js日期格式化) 方法一: // 对Date的扩展,将 Date 转化为指定格式的String // 月(M).日(d).小时(h).分(m).秒(s). ...

  7. [新手教程]windows 2003 php环境搭建详细教程(转)

    对于windows服务器的php环境配置一直是是新人朋友的难题,也难倒了很多高手.这里分享一个新手教程,给那些建站新人使用.本教程来自朋友吴文辉的博客,欢迎大家有时间可以访问他的博客:吴文辉博客htt ...

  8. 第13章 Spring框架的设计理念与设计模式分析

    13.1 Spring的骨骼架构 最核心的组件是:Core, Context, Bean. 13.1.1 Spring的设计理念 Spring最核心的组件是Bean组件.Spring解决的最关键的问题 ...

  9. select,poll,epoll,selectors

    一 了解select,poll,epoll IO复用:为了解释这个名词,首先来理解下复用这个概念,复用也就是共用的意思,这样理解还是有些抽象, 为此,咱们来理解下复用在通信领域的使用,在通信领域中为了 ...

  10. storm和kafka整合

    storm和kafka整合 依赖 <dependency> <groupId>org.apache.storm</groupId> <artifactId&g ...