正确理解ContentPresenter
下图显示继承关系:
ContentControl:Control (在Control類並沒有Content屬性, 所以在這之上再寫了一個ContentControl, 使控件有Content屬性可以顯示內容)
ContentPresenter:FrameworkElement (ContentPresenter一般用在CT里负责把Control指定的Content显示出来)
Control:FrameworkElement
ItemsControl:Control
ItemsPresenter:FrameworkElement

接著來我們看一下實例:
使用ContentPresenter
<ContentControl Content="YangMark">
<ContentControl.Template>
<ControlTemplate TargetType="ContentControl">
<ContentPresenter/>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
輸出結果: YangMark
正確顯示Content!!
不使用ContentPresenter
<ContentControl Content="YangMark">
<ContentControl.Template>
<ControlTemplate TargetType="ContentControl">
<ContentPresenter/>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
輸出結果:
無法顯示出Content!!
結論1:ContentPresenter通常出現在ControlTemplate內,且若不使用ContentPresenter則Content屬性就無法正常顯示。
實例2:ContentPresenter中的ContentSource屬性
為什麼只為了顯示出Content屬性要大費周張弄出ContentPresenter呢??
我們可以先比較以下兩種代碼不同之類,
<ContentControl Content="YangMark" ContentStringFormat="Hello!! {0}">
<ContentControl.Template>
<ControlTemplate TargetType="ContentControl">
<ContentPresenter ContentSource="Content"/>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
<ContentControl Content="YangMark" ContentStringFormat="Hello!! {0}">
<ContentControl.Template>
<ControlTemplate TargetType="ContentControl">
<ContentPresenter Content="{TemplateBinding Content}"/>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
輸出結果:YangMark
僅出現Content屬性的內容!!
結論2:<ContentPresenter/>與<ContentPresenter ContentSource="Content"/> 意義上是相同的。
写ContentSource它們同時綁定了Content, ContentStringFormat, ContentTemplate和ContentTemplateSelector等內容
若僅用Content="{TemplateBinding Content}"代表只綁定Content屬性而已,还要手动绑定其他ContentStringFormat, ContentTemplate和ContentTemplateSelector等。
實例3:ContentSource的應用
以HeaderContentControl為例,使用ContentPresenter綁定內容屬性。
<HeaderedContentControl Header="Header" HeaderStringFormat="I'm {0}"
Content="Content" ContentStringFormat="I'm {0}">
<HeaderedContentControl.Template>
<ControlTemplate TargetType="HeaderedContentControl">
<DockPanel>
<ContentPresenter ContentSource="Header" DockPanel.Dock="Top"></ContentPresenter>
<!--等同於<ContentPresenter ContentSource="Content"/>-->
<ContentPresenter></ContentPresenter>
</DockPanel>
</ControlTemplate>
</HeaderedContentControl.Template>
</HeaderedContentControl>
輸出結果:
I'm Header
I’m Content
結論3:ContentSource若指定對象為Content是可以省略的,若不為Content(如:Header)則不能省略。
總結:
Content, ContentStringFormat, ContentTemplate和ContentTemplateSelector等屬性, 我將它們稱為內容屬性.
1. ContentPresenter的作用就是用來顯示內容屬性
2.ContentSource若指定對象為Content,則等同於<ContentPresenter/>; 若指定對象不為Content,
則必須使用ContentSource聲明指定的對象.
參考資料:
<Window.Resources>
<Style TargetType="ContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<!-- 这里等价于直接<ContentPresenter /> -->
<!-- 强调一下直接用ContentPresenter其ContentSource属性为Content -->
<ContentPresenter ContentSource="Content"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<ContentControl ContentStringFormat="你好:{0}">Mgen</ContentControl>
结果会输出:你好:Mgen。
如果把上面ContentPresenter改用TemplateBinding绑定ContentControl的Content属性:
<ContentPresenter Content="{TemplateBinding Content}"/>
结果只会输出:Mgen。
此时其实ContentStringFormat,ContentTemplate和ContentTemplateSelector都不会管用的,那么只能再用TemplateBinding都把他们在ContentPresenter中绑定好:
<ContentPresenter Content="{TemplateBinding Content}"
ContentStringFormat="{TemplateBinding ContentStringFormat}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"/>
当然ContentPresenter不仅限于ContentControl,可以用在任何类似ContentControl.Content这样的控件属性中,比如HeaderedContentControl.Header属性。
这样定义HeaderedContentControl的控件模板:
<Style TargetType="HeaderedContentControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="HeaderedContentControl">
<DockPanel>
<Border DockPanel.Dock="Top">
<ContentPresenter ContentSource="Header"/>
</Border>
<!-- 等于:<ContentPresenter ContentSource="Content"/> -->
<ContentPresenter/>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
示例:
<HeaderedContentControl Header="Header"
Content="Content"
HeaderStringFormat="上:{0}"
ContentStringFormat="下:{0}"/>
结果:

如果用Content来绑定Header属性:
<ContentPresenter Content="{TemplateBinding Header}"/>
那么你还得再次绑定ContentStringFormat,ContentTemplate和ContentTemplateSelector属性,所以记住总是用ContentPresenter.ContentSource属性。
正确理解ContentPresenter的更多相关文章
- Js位置与大小(1)——正确理解和运用与尺寸大小相关的DOM属性
在web开发中,不可避免遇到要计算元素大小以及位置的问题,解决这类问题的方法是利用DOM提供的一些API结合兼容性处理来,所有内容大概分3篇左右的文章的来说明.本文作为第一篇,介绍DOM提供的与尺寸大 ...
- 【转】正确理解PHP程序编译时的错误信息
我们编写程序时,无论怎样小心谨慎,犯错总是在所难免的.这些错误通常会迷惑PHP编译器.如果开发人员无法了解编译器报错信息的含义,那么这些错误信息不仅毫无用处,还会常常让人感到沮丧. 编译PHP脚本时, ...
- 如何正确理解正则表达式中的分隔符 \b
前言:好久不见,博客园. 最近在学习研究regex,其中有个特迷惑自己的知识点是分隔符 ( word boundary) [\b] (注:为了方便,后文都以[]来包含字符,并不是reg规则里面的[] ...
- Java进阶(七)正确理解Thread Local的原理与适用场景
原创文章,始自发作者个人博客,转载请务必将下面这段话置于文章开头处(保留超链接). 本文转发自技术世界,原文链接 http://www.jasongj.com/java/threadlocal/ Th ...
- IM开发基础知识补课:正确理解前置HTTP SSO单点登陆接口的原理
1.前言 一个安全的信息系统,合法身份检查是必须环节.尤其IM这种以“人”为中心的社交体系,身份认证更是必不可少. 一些PC时代小型IM系统中,身份认证可能直接做到长连接中(也就是整个IM系统都是以长 ...
- IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列
1.引言 消息是互联网信息的一种表现形式,是人利用计算机进行信息传递的有效载体,比如即时通讯网坛友最熟悉的即时通讯消息就是其具体的表现形式之一. 消息从发送者到接收者的典型传递方式有两种: 1)一种我 ...
- 正确理解CAP定理
前言 CAP的理解我也看了很多书籍,也看了不少同行的博文,基本每个人的理解都不一样,而布鲁尔教授得定义又太过的简单,没有具体描述和场景案例分析.因此自己参考部分资料梳理了一篇与大家互相分享一下. 标题 ...
- 正确理解 LEAL (Load Effective Address) 指令
LEAL: leal S, D -> D ← &S 在 CSAPP (Computer Systems: A Programmer’s Perspective) 中,对 LE ...
- 条目二十八《正确理解由reverse_iterator的base()成员函数所产生的iterator的用法》
条目二十八<正确理解由reverse_iterator的base()成员函数所产生的iterator的用法> 迭代器的种类一共有四种,上面已经说过了.这里就不再次写出来. 这一个条目主要是 ...
随机推荐
- 【转】发布的QT程序无法显示图标和图片的问题
在windows下编译好的QT程序在其他没有安装QT的机器上会出现图标和图片无法正常显示的问题. 这时我们可以通过以下方式来解决: 在release文件夹里创建plugins文件夹,并将QT安装目录下 ...
- Mac 上安装MySQL
http://blog.neten.de/posts/2014/01/27/install-mysql-using-homebrew/ http://www.wkii.org/mac-os-x-ins ...
- matplotlib 绘制柱状图的几个例子
1 error bar #!/usr/bin/env python # a bar plot with errorbars import numpy as np import matplotlib.p ...
- 深入理解ob_flush/flush
ob_flush/flush在手册中的描述, 都是刷新输出缓冲区, 并且还需要配套使用, 所以会导致很多人迷惑… 其实, 他们俩的操作对象不同, 有些情况下, flush根本不做什么事情.. ob_* ...
- OpenGL ES之GLSurfaceView学习一:介绍
原文地址::http://120.132.134.205/cmdn/supesite/?uid-5358-action-viewspace-itemid-6527 GLSurfaceView是一个视图 ...
- http tcp联系区别
术语TCP/IP代表传输控制协议/网际协议,指的是一系列协议.“IP”代表网际协议,TCP和UDP使用该协议从一个网络传送数据包到另一个网络.把IP想像成一种高速公路,它允许其它协议在上面行驶并找到到 ...
- 【Android】Handler使用入门
本讲内容:Handler使用入门 当用户点击一个按钮时如果执行的是一个常耗时操作的话,处理不好会导致系统假死,用户体验很差,而Android则更进一步,如果任意一个Acitivity没有响应5秒钟以上 ...
- YII Framework学习教程-YII的安全
web应用的安全问题是很重要的,在“黑客”盛行的年代,你的网站可能明天都遭受着攻击,为了从某种程度上防止被攻击,YII提供了防止攻击的几种解决方案.当然这里讲的安全是片面的,但是值得一看. 官方提供的 ...
- spring初探1
spring初探1 关于新建对象,对象依赖的三种方式比较 场景 某个交易的业务组建拆分,为原先的功能模块新写了一个业务组件 使用new. 修改上层代码的对象生成部分( 如果不是面向接口编程,简直就是灾 ...
- Json.Net 使用属性定义日期的序列化格式
如果一个实体类里所有的时间即DateTime类型的字段,都处理成统一格式的话,可以使用如下方式: IsoDateTimeConverter timeFormat = new IsoDateTimeCo ...