WPFコントロールテンプレートとデータテンプレートの違い

WPFのコントロールは、

  1. CheckBoxのような単一のアイテムを保有するコンテンツコントロール
  2. ListBoxのような複数のアイテムを保有するアイテムコントロール
  3. Gridのようなレイアウトを制御するパネルコントロール

の3種があります。今回は1, 2のコンテンツコントロール、アイテムコントロールを対象とした『テンプレート』についてのお話。コンテンツコントロール、アイテムコントロールいずれも両テンプレートをそれぞれ以下のプロパティ名で公開しています。

template_property

以下Buttonを例に、簡単に違いを見ておきます。

 

1.コントロールテンプレート

コントロールテンプレートは「コントロール自身の見た目を決定するもの」と言えます。良く言われる話ですがWPFのコントロールはルックレス[LookLess]、つまり基本的には見た目を持ちません。

そのため通常のButtonは、 normal_button_image←こんなですが、

内部的には normal_button←のような構成を取っています。

この一番下部にあるButtonがWPFのButtonです。ButtonChromeやContentPresenterが見た目を制御していると言って良いでしょう。

見た目をいじったものとして、control_template_image←こんなButtonがすぐ作れますが、これは

内部的にはcontent_template←のような構成を取っています。

これを構成するXAMLを見ておくと、

<Button>
    コンテンツ
    <Button.Template>
        <ControlTemplate TargetType="Button">
            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                <ContentPresenter/>
            </Border>
        </ControlTemplate>
    </Button.Template>
</Button>

こんな感じ。ControlTemplateにターゲットタイプを指定していることに注意、これはContentPresenterが動作するために必要です。というのもContentPresenterは内部でターゲットタイプを必要とするBindingを持っているため。ContentPresenterを持たないボタンなら不要です。TemplateBindingはこのControlTemplateが割り当てられる先(つまりButton)のプロパティと同じ値を取ります、というものです。上の例で見るように、Buttonを例にするとコントロールテンプレートとは、『ボタンとは四角くて、周囲が少し縁取られており、マウスがホバーされると色が変わり、コンテンツをコントロールの中心に持った…』という部分をカスタマイズするものです。

ちなみに上で示したButtonのテンプレート構成図は

var control = Application.Current.FindResource(typeof(Button));
using(XmlTextWriter writer = new XmlTextWriter(@"DefaultButtonTemplate.xml", Encoding.UTF8)){
    writer.Formatting = Formatting.Indented;
    XamlWriter.Save(control, writer);
}
Console.WriteLine(XamlWriter.Save(this));

こんなコードで出力することができます。

 

 

2.データテンプレート

データテンプレートは「コントロールに割り当てられたデータの見た目を定義するもの」と言えます。コントロールテンプレートがボタンの”コントロール”としての部分をカスタマイズするものなのに対し、データテンプレートはそれに表示されるコンテンツの部分をカスタマイズするものです。

私的な印象では、データテンプレートの99% はアイテムコントロールで使われるのですが(リスト形式のデータを表現するのに便利だから)、コンテンツコントロールにもムリヤリ適用するとこんな感じ→ datatemplate_image

コントロールテンプレートはいじってないのでボタンらしい感じながら、表示されているものがカスタマイズされた感じなことに気付くと思います。これを実現するデータテンプレートは参考までにこんな感じです。

<Button x:Name="dataTemplatedButton" Margin="50,50,50,50">
    <Button.ContentTemplate>
        <DataTemplate>
            <StackPanel Orientation="Vertical">
                <TextBlock Text="{Binding}" FontSize="12"/>
                <TextBlock Text="{Binding}" FontSize="8"/>
            </StackPanel>
        </DataTemplate>
    </Button.ContentTemplate>
</Button>

上のような「サイズ違いで2コ同じコンテンツを並べたい」等の場合はデータテンプレートを使います。

 

3.どちらを使うか

コントロールテンプレートは多くの場合TemplateBindingを使い、テンプレート親とのコントロールとしてのデータとのバインドを作成します。一方でデータテンプレートはBindingを使い、割り当てられたデータとのバインドを作成します。カスタマイズしたいものがコントロール自身なのか、割り当てられるデータなのか、でどちらを使うかが決まります。

状況によっては、コントロールテンプレート、データテンプレートどちらを使っても可能なことがあります。この場合これらテンプレートを再利用する時のことを考えると良いと思います。そのカスタマイズした結果できるであろうコントロールに、別のデータを載せることがあるのかどうか、を考えてみてください。別のデータを載せることもある場合はコントロールテンプレート、別のデータを載せない場合はデータテンプレートと判断してよいかと思います。

まぁコンテンツコントロールの場合はコントロールテンプレート、アイテムコントロールの場合はデータテンプレートと言ってもかなりの割合で正しい選択になるとは思います;

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中