WPFのPresenter(ContentPresenter)

11337 ワード


これは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から継承されるのはコンテンツモデルのコントロールと呼ぶことができる.次のように
WPF的Presenter(ContentPresenter)_第1张图片
ここにContentPresenterの影は見えないようです.次に例を挙げます
ContentPresenterの例
image
ContentPresenterは直接xamlに出力することができ、そのビジュアルツリーにはTextBlockが含まれており、デフォルトのWPFスタイル定義ではContentPresenterに関するスタイルが見つかりません.ContentPresenterは真のコードロジックとスタイルが分離されているのではなく、内部コードにデフォルトのテンプレートが提供されていることを示しています.つまり、内部にテンプレートを作成すると、一般的にはFrameworkElementFactoryでルート要素を作成するが、この方法は複雑すぎてContentPresenter内部のTextBlockのような簡単なデフォルト操作に適している.
では、問題が発生しました.なぜTextBlockを直接使わないのですか.ContentPresenterも包装しますか.
ContentPresenterとTextBlock
上記の質問に答えるには、両者の違いを議論するように、TextBlockを見てみましょう.
<TextBlock Text="Hello"/>

 
 
TextBlockは本当に文字をテーマにした要素ですが、ContentPresenterの機能は文字だけではありません(補足のみ)
WPF的Presenter(ContentPresenter)_第2张图片
ただし、デフォルトでは提示文字に過ぎませんが、両者の概念はまったく異なり、Content属性はstringではなくobjectタイプであり、Contentをデータソースとしてテンプレート(ContentTemplate)を自分で再定義することができます.以下の例です.
WPF的Presenter(ContentPresenter)_第3张图片
これによりContentPresenterは文字の提示に限られなくなる.
ContentControlとContentPresenterの関係を見てみましょう
ContentControlとContentPresenter
まず、再定義されたButtonスタイルを見てみましょう.
WPF的Presenter(ContentPresenter)_第4张图片
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を指定することで指定したソース属性をバインドすることができる
WPF的Presenter(ContentPresenter)_第5张图片
コンテンツモデルは文字を表示するだけでなく、文字を表示するためだけであればContentPresenterは不要であることを覚えておいてください.
親子要素間の関係(ItemsPresenter)
コントロールは、自身の論理を維持するのではなく、親子要素に依存する場合があります.控訴のContentPresenterのように、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>

ItemsControlのデフォルトコンテナとしてStackPanelを使用するビジュアルツリー
image
まずはここまで