这是2年前写了一篇文章

http://www.cnblogs.com/Clingingboy/archive/2008/07/03/wpfcustomcontrolpart-1.html

我们先来看MSDN对其的介绍

Displays the content of a ContentControl

似乎其是为ContentControl定身量做的.

为了理解这一点,首先我们要对WPF内容模型有所了解,上面这篇文章有提到过ContentControl继承自Control,多了Content属性,继承自ContentControl的均可以称之为内容模型的控件.如下

这里似乎看不到ContentPresenter的影子.下面来举一些例子

一个ContentPresenter的例子

ContentPresenter可以直接在xaml中输出,其视觉树中包含一个TextBlock,在默认的WPF样式定义中找不到任何关于ContentPresenter的样式,说明了ContentPresenter并非是真正代码逻辑与样式分离的,而是在内部代码中提供了一个默认的模板即呈现了TextBlock,如果在内部创建模板的话,一般均会采用FrameworkElementFactory创建根元素,但这种方式太过于复杂,适用于一些简单默认操作,就如ContentPresenter内部的TextBlock.

那么问题出来了,为什么不直接用TextBlock呢,还要包装一个ContentPresenter?

ContentPresenter与TextBlock

如要回答上面的问题,那么就犹如来讨论两者的区别,我们来看下TextBlock

<TextBlock Text="Hello"/>

TextBlock是一个真正以文字为主题的元素,而ContentPresenter的功能就不只呈现文字了(只补)

只不过默认是呈现文字而已,但两者概念完全不同,Content属性是object类型,而非string,可以自己以Content为数据源而重新定义模板(ContentTemplate),如下示例

这样的话ContentPresenter将不再局限于文字的呈现.

下面来看看ContentControl与ContentPresenter的关系

ContentControl与ContentPresenter

先看一个被重新定义的的Button样式

上面可以看到,使用ContentPresenter非常的方便,只要将ContentPresenter放在模板中即可,也不需要做任何的额外的绑定(难道不需要做吗?只不过ContentPresenter内部帮我们做了默认的绑定),但如果使用TextBlock呢?如下还是需要做绑定的

        <Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<TextBlock Text="{TemplateBinding Content}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

如上看来我们还不如说ContentControl是ContentPresenter的一个特例,而ContentPresente

ContentPresenter则是ContentControl的基础.为了适配ContentPresenter,ContentControl提供了内容模型的相关属性,本质上ContentPresenter并非仅仅只是用到ContentControl而已,ContentPresenter可以通过指定ContentSource来绑定指定的源属性

记住内容模型不仅仅只是呈现文字而已,如果只是为了呈现文字的话,是不需要ContentPresenter的

父子元素之间的关系(ItemsPresenter)

有时候控件并非维护本身逻辑,而是依赖于父子元素的,如了上诉的ContentPresenter,我们还有一个非常常用的ListBox控件,因为继承自ItemsControl,所以有一个ItemsPanel属性作为集合元素承载容器,但集合控件本身却不负责呈现控件,那么这个任务就留给了子元素ItemsPresenter,其实用也很简单,只要把ItemsPresenter放在内部模板中,那么ItemsPresenter则会去检测父元素是否为集合控件,然后将ItemsPanel添加到其内部视觉树当中

        <Style x:Key="{x:Type ItemsControl}"
TargetType="{x:Type ItemsControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="true">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

如下视觉树,StackPanel作为ItemsControl的默认容器

先到这里吧

最新文章

  1. MySQL int(11)及int(M)解析
  2. javascript 对象初探(二)--- 返回对象的函数
  3. C语言的传值与传址调用
  4. Extjs中给同一个GridPanel中的事件添加参数的方法
  5. iOS - Swift NSTimer 定时器
  6. [系统开发] FileMaker进销存系统
  7. 微信支付配置信息,JSAPI接口,H5调用微信js接口支付,微信公众号支付
  8. linux安装tomcat(转载:http://blog.csdn.net/zhuihunmiling/article/details/8977387)
  9. MySQL索引及Explain及常见优化
  10. Wordpress主题中常用代码总结
  11. Java 课程设计 &quot;Give it up&quot;小游戏(团队)
  12. kernel笔记——内核同步与锁
  13. Python Selenium 常用方法总结(不断补充)
  14. es6那些事儿
  15. easyui datagrid 弹出页面会出现两个上下滚动条处理办法!
  16. 多线程学习-ListenableFuture使用介绍以及示例
  17. 深入浅出HTTPS基本原理
  18. Linux监控远程端口是否开启脚本
  19. 线上Bug修复流程
  20. 剑指offer-数值的整数方

热门文章

  1. Censoring(bzoj 3940)
  2. 【BZOJ2693】jzptab (莫比乌斯反演)
  3. Spring Boot的web开发&amp;静态资源配置方式
  4. Android 4.4 不休眠+不锁屏+默认中文+去除导航栏
  5. js 克隆数据 (数组的深浅拷贝)
  6. Codefroces Gym101572 I.Import Spaghetti-有向图跑最小环输出路径(Floyd)
  7. 洛谷—— P1375 小猫
  8. 3.4 熟练掌握动态规划——状态压缩DP
  9. mysql 安装配置及经常使用操作
  10. java设计模式之-建造者模式