zoukankan      html  css  js  c++  java
  • WPF的Presenter(ContentPresenter)

    WPF的Presenter(ContentPresenter)

    2010-12-20 14:34 by Clingingboy, 10619 阅读, 3 评论, 收藏, 编辑

    这是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的均可以称之为内容模型的控件.如下

    image

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

    一个ContentPresenter的例子

    image

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

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

    ContentPresenter与TextBlock

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

    <TextBlock Text="Hello"/>
    

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

    image

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

    image

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

    下面来看看ContentControl与ContentPresenter的关系

    ContentControl与ContentPresenter

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

    image

    上面可以看到,使用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来绑定指定的源属性

    image

    记住内容模型不仅仅只是呈现文字而已,如果只是为了呈现文字的话,是不需要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的默认容器

    image

    先到这里吧

  • 相关阅读:
    sublime text 4 vim 插件配置
    ssh-keygen 的使用
    distribution transaction solution
    bilibili 大数据 视频下载 you-get
    Deepin 20.2.1 安装 MS SQL 2019 容器版本
    【转】使用Linux下Docker部署MSSQL并加载主机目录下的数据库
    【转】You Can Now Use OneDrive in Linux Natively Thanks to Insync
    dotnet 诊断工具安装命令
    Linux 使用 xrandr 设置屏幕分辨率
    【转】CentOS 7.9 2009 ISO 官方原版镜像下载
  • 原文地址:https://www.cnblogs.com/changbaishan/p/4042648.html
Copyright © 2011-2022 走看看