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

    来自:http://www.cnblogs.com/Clingingboy/archive/2010/12/20/1911388.html

     

    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>
    

    WPF中不同的Binding类型,在http://blog.csdn.net/xxchen2/article/details/4552554中看到下面的片段,得出结论//WPF中({Binding RelativeSource={RelativeSource TemplatedParnet}}”等价于“{TemplateBinding}”)?

     <Style TargetType="{x:Type local:TemplatedParent}">

            <Setter Property="Background" Value="Green"/>

            <Setter Property="Template">

                <Setter.Value>

                    <ControlTemplate TargetType="{x:Type local:TemplatedParent}">

                        <Grid>

                            <Ellipse>

                                <Ellipse.Fill>

                                    <SolidColorBrush Color="{Binding Path=Background.Color,RelativeSource={RelativeSource TemplatedParent}}"/>

                                </Ellipse.Fill>

                            </Ellipse>

                        </Grid>

                    </ControlTemplate>

                </Setter.Value>

            </Setter>

        </Style>

     

    在上例中是这样使用TemplatedParent的:

    <SolidColorBrush Color="{Binding Path=Background.Color,RelativeSource={RelativeSource TemplatedParent}}"/>

     

     

     

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

    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

    先到这里吧

  • 相关阅读:
    思维体操:用c#简单实现按一定规则输出有序数列
    浅谈c#中使用lock的是与非
    强大的在线IDE:CodeRun
    【百度地图API】如何利用地图API制作汽车沿道路行驶的动画?——如何获得道路层数据
    如何利用【百度地图API】,制作房产酒店地图?(中)——使用右侧列表打开信息窗口
    如何利用【百度地图API】,制作房产酒店地图?(下)——结合自己的数据库
    【百度地图API】如何制作“从这里出发”“到这里去”——公交篇
    【百度地图API】建立全国银行位置查询系统(五)——如何更改百度地图的信息窗口内容?
    如何利用【百度地图API】,制作房产酒店地图?(上)——制作自定义标注和自定义信息窗口
    【百度地图API】交你如何用百度地图搜索自己的数据!不需数据库!
  • 原文地址:https://www.cnblogs.com/zuiyirenjian/p/2659688.html
Copyright © 2011-2022 走看看