第4回 “見た目”を決めるコントロール・テンプレート連載 WPF/Silverlight UIフレームワーク入門(1/3 ページ)

WPF/Silverlightの外観を簡単に変更できるコントロール・テンプレートとは? さらにUIフレームワークのUI要素の階層をまとめる。連載最終回。

» 2009年07月13日 00時00分 公開
[八巻雄哉グレープシティ株式会社]
連載 WPF/Silverlight UIフレームワーク入門
業務アプリInsider/Insider.NET

powered by Insider.NET

「連載 WPF/Silverlight UIフレームワーク入門」のインデックス

連載目次

 前回に引き続きWPF UIフレームワークの“見た目”に関する機能を説明する。連載最終回となる今回は、コントロール・テンプレートを紹介したいと思う。

■コントロール・テンプレート

 これまでのWindowsフォームでもそうであったように、WPF UIフレームワークのコントロールの“見た目”は、プロパティ設定により変更できる。例えばButtonコントロールの場合であれば、背景色はBackgroundプロパティ、枠線の色はBorderBrushプロパティで変更可能だ。

 しかしながらWindowsフォームの場合、このようにして変更できるのは、ある程度の“見た目”である。例えばButtonコントロールのボタンの形そのものを変更したい場合、プロパティ設定では変更できない。Windowsフォームなど、これまでのWin32ベースのコントロールでこのような要求に応える場合、コントロールを自前で描画する「オーナー描画」と呼ばれる方法が用意されていた。しかしながら、オーナー描画はグラフィックス・メソッドなどを使用して、すべての描画を独自に行わなければならないため、コントロールに対する深い知識と多量のコードが必要になり、そう簡単に行えるものではなかった。

 WPF UIフレームワークの場合、このような直接的にプロパティが用意されていない“見た目”の変更も、実はプロパティ設定だけで比較的簡単に変更できるようになっている。そのプロパティの名は「Templateプロパティ」である。

Templateプロパティと既定のコントロール・テンプレート

 WPF UIフレームワークのすべてのコントロール(Controlクラス、およびその派生クラス)はTemplateプロパティを持っており、このプロパティ対して「コントロール・テンプレート」を設定することで、ビジュアル構造を再定義できる仕組みになっている。

 例えば、下記のXAMLコードの2つ目のボタンのように、Templateプロパティにnull(VBではNothing)参照を設定すると、デフォルトのコントロール・テンプレートが上書きされてしまうため、そのボタンの外観は表示されなくなる(外観が存在しない状態となる)。

<StackPanel>
  <Border BorderBrush="Blue" BorderThickness="1"
    Height="100" Padding="10">

    <Button Content="Button"/>

  </Border>

  <Border BorderBrush="Blue" BorderThickness="1"
    Height="100" Padding="10">

    <Button Content="Button" Template="{x:Null}"/>

  </Border>
</StackPanel>

2つのボタンを配置し、片方のボタンのTemplateプロパティにnull(VBではNothing)参照を設定したコード例(XAML)
「{x:Null}」はプロパティの値としてnull(VBではNothing)参照を指定するマークアップ拡張機能。ボタンの外観が表示されていないことを確認しやすくするために、ボタンの回りには青色の枠線を表示させている。

 このXAMLコードを実際に実行したのが、次の画面である。

ボタンのTemplateプロパティにnull(VBではNothing)参照を設定した場合の表示例(上から2つ目の青い枠線の中)
上記はWPFでの表示結果であり、Silverlight 2の場合にはボタンの領域が紺色で描画される。

 このように、Templateプロパティにnull(VBではNothing)参照を設定すると、外観がまったくない状態になるという事実から、1つ目のボタンに見ることができるデフォルトの外観も、実際にはコントロール・テンプレートによって定義されているということが導き出せる。デフォルトの外観を定義するコントロール・テンプレートが、実行時にはボタンのTemplateプロパティに設定されているということだ。

 そのため、設計時にTemplateプロパティの設定値を見ても、デフォルトのコントロール・テンプレートの内容を確認することはできない。デフォルトのコントロール・テンプレートの内容を確認する手段としては、以下のようないくつかの方法が存在する。

 なお、WPFのコントロールの外観は、Windowsのデスクトップ・テーマによって異なる。このため、デフォルトの外観を定義しているコントロール・テンプレートは1つではなく、デスクトップ・テーマの数だけ存在する。

固定的なコントロール・テンプレート

 コントロール・テンプレートの概要を理解したところで、具体例を使って、より詳細な内容を見ていこう。下記のコードは、非常に単純な角が丸いボタンを、コントロール・テンプレートを使って作成した例だ。

<Button>
  <!-- コントロール・テンプレートの定義 -->
  <Button.Template>
    <ControlTemplate TargetType="Button">
      <Border Background="LightGreen" CornerRadius="30" Padding="10">
        <TextBlock Text="テンプレート"
          VerticalAlignment="Center" HorizontalAlignment="Center"/>
      </Border>
    </ControlTemplate>
  </Button.Template>
</Button>

角が丸いボタンを、コントロール・テンプレートを使って作成するコード例(XAML)

 上記のXAMLコードによって表示されるButtonコントロールの外観は、以下の画面のようになる。

コントロール・テンプレートを使って外観を変更した角が丸いボタンの画面

 すでに説明したとおり、コントロール・テンプレートはTemplateプロパティの値として設定する。そのため、リソース、もしくはリソースとスタイルの両方を利用して、コントロール・テンプレートによる外観を複数のコントロールで共有できる。

 以下のコードでは、先ほどのコントロール・テンプレートをリソースとして登録し、それを2つのButtonコントロールから参照している。

<StackPanel>

  <StackPanel.Resources>
    <ControlTemplate x:Key="ButtonTemplate"  TargetType="Button">
      <Border Background="LightGreen" CornerRadius="30" Padding="10">
        <TextBlock Text="テンプレート"
          VerticalAlignment="Center" HorizontalAlignment="Center"/>
      </Border>
    </ControlTemplate>
  </StackPanel.Resources>

  <Button Content="Button1"
    Template="{StaticResource ButtonTemplate}" Margin="30"/>

  <Button Content="Button2"
    Template="{StaticResource ButtonTemplate}" Margin="30"/>

</StackPanel>

コントロール・テンプレートをリソースとして登録して共有したコード例(XAML)

 同じコントロール・テンプレートを参照しているため、以下の画面のように、2つのButtonコントロールは当然ながらどちらも同じ外観となる。

2つのButtonコントロールで同じコントロール・テンプレートを参照した画面

 しかしながら、上記のコントロール・テンプレートには大きな問題がある。それは、それぞれのButtonコントロールにおいてContentプロパティを“Button1”、“Button2”と設定しているにもかかわらず、それがボタンの表示文字列に反映されていないという点だ。

 この問題の原因は、コントロール・テンプレート内で固定的に“テンプレート”と表示するように定義してしまっている部分にある。

       1|2|3 次のページへ

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。