wpf特殊属性:正确理解ContentPresenter(转载)

原文地址:https://www.cnblogs.com/shawnzxx/p/3346975.html

下图显示继承关系:

ContentControl:Control (在Control類並沒有Content屬性, 所以在這之上再寫了一個ContentControl, 使控件有Content屬性可以顯示內容)

ContentPresenter:FrameworkElement (ContentPresenter一般用在CT里负责把Control指定的Content显示出来)

Control:FrameworkElement

ItemsControl:Control

ItemsPresenter:FrameworkElement

ScreenClip

 

接著來我們看一下實例:

使用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>

輸出結果:Hello!! YangMark
 
            <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聲明指定的對象.

 

參考資料:

比如使用ContentPresenter的ContentSource,然后在ContentControl中设置ContentStringFormat:

<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}"/>

结果:

image

 

如果用Content来绑定Header属性:

<ContentPresenter Content="{TemplateBinding Header}"/>

那么你还得再次绑定ContentStringFormat,ContentTemplate和ContentTemplateSelector属性,所以记住总是用ContentPresenter.ContentSource属性。

 

posted @ 2023-06-14 22:05  世人皆萌  阅读(514)  评论(0编辑  收藏  举报