リソースとスタイルとテンプレート

WPF再入門状態なので忘れないように忘れてもいいようにメモ。

(MSDN)スタイルとテンプレート に書いてあることの要約。

具体的に組んでみる例は次回やります

リソース ルックアップ

アプリケーションに含まれるアセンブリは複数のResourceDictionaryを定義できる。

あるResourceDictionaryは MergedDictionaries を利用することで、依存する他のリソースのUriを指定できる。

FrameworkElementが暗黙的にリソースを必要とする際は以下の順で探索が行われる。

  • 階層の下の方から上の方に向かって順にElementのリソースプロパティを探索
  • Application.Resources を探索
  • アセンブリの Themes/ フォルダ以下にある、端末のテーマ設定にマッチしたリソース
  • アセンブリの Themes/Generic.xaml
  • システム設定にある、端末のテーマ設定にマッチしたリソース)

アセンブリが分かれている場合や標準UI部品のリソースがどのように探索されているのかはよくわからない。

(MSDN)リソース ディクショナリ

Style

  • 型名 System.Windows.Style
  • プロパティ名 Style

リソースのうち最も複雑なのはStyleで、FrameworkElement または FrameworkContentElement から派生する任意の要素に対して任意のプロパティを設定することができる。

テンプレートの指定もスタイルに含めることができる。
また、スタイルはBasedOnプロパティを指定することで実行時に継承できる。

UI部品のコンストラクタからprotected プロパティのDefaultStyleKeyを指定することで、UI部品は継承元の部品のスタイルの影響を避けることができる。標準UI部品のスタイルを回避するだけなら OverridesDefaultStyle を設定するだけでよいが、継承元がシステム設定のテーマスタイルではない場合もあるかもしれない。

ControlTemplate

  • 型名 System.Windows.Controls.ControlTemplate
  • プロパティ名 Template

UI要素内部のUI構造を変更する仕組み。
たとえば枠が丸いボタンなどを表現できる。
UI部品へのスタイル指定にはたいていControlTemplateが含まれる。
UI要素のプロパティをその内部構造から参照するには{TemplateBinding} マークアップ拡張を利用する。

DataTemplate

  • 型名 System.Windows.DataTemplate
  • プロパティ名 Button.ContentTemplate, ListBox.ItemTemplate など

ContentControl の派生型である ButtonやListBoxItemの既定のTemplateの中にはContentPresenterがあって、そのContentTemplateはTemplateBindingで親コントロールのContentTemplateを参照している。

ListBoxの場合、ListBoxItemのContentTemplateは次のように決定される。

  • もし ListBox.ItemTemplate が設定されていればそれを選択
  • そうではなく、もし ListBox.ItemTemplateSelector が設定されていればそれを使って選択
  • そうではないなら null のまま

ContentPresenterはContentTemplateがnull の場合、リソースからDataType属性がContentにマッチするDataTemplateを選択する。

DataTemplate内部のデータバインディングやDataTriggerは長くなりそうなのでまた今度。

(MSDN)データ テンプレートの概要
(MSDN)データ バインディングの概要
(MSDN)ListBox のスタイルとテンプレート
(MSDN)Button のスタイルとテンプレート

ItemsPanelTemplate

  • 型名 System.Windows.Controls.ItemsPanelTemplate
  • プロパティ名 ListBox.ItemsPanel など

ListBox などの集合を扱うUI部品は ItemsControl 型を継承していて、ItemsPanel プロパティを持つ。
ItemsControlはControlTemplate中の の書かれた位置に、ItemsPanel プロパティで指定されたテンプレートを展開する。
このテンプレートに設定するUI構造のルートは常にPanel型のはず

たとえばリストアイテムを横方向に並べる際などに使われる。

VisualStateGroup

最近のWPFでははUI部品の状態は Visual State Manager で表現するらしい。
(MSDN Magazine)Silverlight 4 における滑らかな UI

UI部品が独自の状態を持つ場合、それをUIに反映させるにはクラス実装が TemplateVisualState を定義して、 VisualStateManager.GoToState() を適切に呼び出す。