一、前言

这个类单独拿出来讲,是因为它很重要,但又很迷惑,很多人可能都不知道它。说重要是因为一般DataTemplate的载体(作用对象)就是它,而且你用Blend for VS敲开一个控件,你会发现每每都存在它。说迷惑是因为,你在相关类的属性中发现不了它。


二、认识

2.1 涉及名词释义

涉及的部分英语单词,后面用中文叫了。

英文名称中文译名是什么?
ContentControl内容控件class
DataTemplate数据模板class
ControlTemplate控件模板class
ContentPresenter内容呈现器class
Template控件模板Control类中ControlTemplate类型的属性
ContentTemplate内容模板ContentControl中DataTemplate类型的属性
Notes:
所以后面说Template就是指Control类中ControlTemplate类型的属性,即ControlTemplate Template
ContentTemplate是指ContentControl类中DataTemplate类型的属性,
两者区别就是,Template时指的是Control中的属性,ControlTemplate指类,
ContentTemplate与DataTemplate同理。

2.2 定义

也不花里胡哨,直接看看官方文档的定义。
在这里插入图片描述
作用言简意赅,用于呈现ContentControl的Content,即显示内容控件的内容。

下面是ContentPresenter类的继承关系类图,特别注意其属性,它只有ContentTemplate属性,没有Template属性,这就说明了它的用途必定与DataTemplate有关。
在这里插入图片描述

2.3 例子

下面展示一个按钮的样式,该样式设置了Button的ControlTemplate。该ControlTemplate定义了一个在Grid元素内部的椭圆形按钮。ContentPresenter标记了按钮应被呈现,且位于Grid中水平垂直居中。

下面是其XAML,

<Style TargetType="Button">
	<!--值设为true,使其不从主题中获取任何属性-->
    <Setter Property="OverridesDefaultStyle" Value="True"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid>
                    <Ellipse Fill="{TemplateBinding Background}"/>
                    <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

主窗体中添加一个按钮,

	<Grid>
        <Button Content="Content" Background="LightBlue"/>
    </Grid>

效果如下图,你的按钮改变了外观。
在这里插入图片描述
此时,你若把ContentPresenter注释掉,

<!--ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/-->

运行效果如下,
在这里插入图片描述
Button中的内容就不显示了,至此,ContentPresenter这个名词也非常好理解了,就是内容呈现器——字面意思,用于呈现内容的。

⭐2.4 附注

通常,会使用ContentPresenter在一个ContentControl的ContentTemplate属性中来指定内容添加的位置。 每个ContentControl类型的默认控件模板中都会有一个ContentPresenter(来呈现ContentControl的内容)。

当一个ContentPresenter对象位于ContentControl的ControlTemplate中时,该对象的Content,ContentTemplate以及ContentTemplateSelector属性会从ContentControl中的相同名称的属性中取得值(就如2.3例子的情况)。(从下面继承关系的类图可知,ContentControl和ContentPresenter中都有一个ContentTemplate属性,意思就是ContentPresenter的ContentTemplate会使用ContentControl的ContentTemplate数据)
在这里插入图片描述
你可以通过设置ContentSource属性或者绑定的方式来让ContentPresenter属性从其他的模板化父亲(Templated Parent)的属性中获取值。
     ~~~~     ContentPresenter使用以下的逻辑来显示Content内容(流水账,看懂两个就好):

  • 如果已经设置了ContentPresenter中的ContentTemplate属性,ContentPresenter会将这个DataTemplate(指的就是ContentTemplate)应用到Content属性上并且显示作为结果的UIElement和它的子元素(将DataTemplate内的控件树显示)。
  • 若设置了ContentTemplateSelector,ContentPresenter就会将合适的DataTemplate应用到Content上并显示作为结果的UIElement和它的子元素。
  • 若有DataTemplate关联到Content,ContentPresenter会将DataTemplate应用到Content上并且显示UIElement和子元素。。
  • 若Content是UIElement对象,UIElement就会被呈现。若UIElement已经有一个父亲,会产生一个异常。
  • 若有一个用于将Content转化为UIElement的TypeConverter,ContentPresenter就会用这个TypeConverter并呈现UIElement。
  • 若有一个用于将Content转化为string的TypeConverter,ContentPresenter就会用这个TypeConverter并创建一个TextBlock来容纳那段string,接着TextBlock会被显示。
  • 若内容是XmlElement,InnerText属性的值会显示在TextBlock中
  • ContentPresenter在Content上调用ToString方法并创建一个TextBlock来容纳这个ToString返回的string。接着TextBlock被显示。

三、参考

微软官方文档

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐