Sample6 / より実用的な設計
About
このTemplateやStyleへの入門資料では、Buttonコントロールを例に解説をしています。サンプルではButtonのTemplateとして、BorderとTextBlockを定義していますが、WPFが提供する本来のButtonコントロールはContentプロパティを持っていて、例えば画像などをButtonの中に表示(設定)することができます。TextBlockではButtonが本来持つContentプロパティの役割を果たすことができません。
実のところ、ControlTemplateが提供するべきButtonコントロールの構成要素はTextBlockではなく、ContentPresenterと呼ばれる要素です。Sample6ではContentPresenterに置き換えて、Buttonの中に画像を表示する例を示します。
多くの資料がButtonを例として挙げているのは、トリガーやデザインの設定が最もシンプルに説明できるためだと思います。
HowTo
Sample5までと比較してControlTemplate内で変更された箇所はTextBlockがContentPresenterになった箇所だけです。実際にButton上に表示されるContentの内容は、テンプレートを利用するButton側で決定できるようにTemplateBindingを利用しています。
ソースコードとしてはButton側も変更されていますが、これについてはButtonコントロールの利用方法について解説する必要が出てくるので、ここでは解説を割愛します。StackPanelをButton.Controlに設定して、さらにそのStackPanelの中に画像とテキストを表示するように工夫してありますが、およそ一般的な利用方法の枠を漏れないでしょう。
<UserControl.Resources> <ControlTemplate TargetType="Button" x:Key="ButtonTemplate"> <Border Name="border" Background="{TemplateBinding Background}" CornerRadius="10" Padding="10"> <ContentPresenter Content="{TemplateBinding Content}" VerticalAlignment="Top" HorizontalAlignment="Right"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="border" Property="Background" Value="Blue" /> </Trigger> <Trigger Property="IsMouseOver" Value="False"> <Setter TargetName="border" Property="Background" Value="{Binding Background, RelativeSource={RelativeSource TemplatedParent} }" /> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </UserControl.Resources> <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> <Button Height="50" Width="200" Background="Green" Template="{StaticResource ButtonTemplate}"> <StackPanel Orientation="Horizontal"> <Image Source="Image/sampleimage.png" Stretch="UniformToFill" /> <Label Content="Hello Template" Foreground="White"/> </StackPanel> </Button> </StackPanel>
これでSample6の内容は終わりです。さらにControlTemplateの具体的な解説も実質的には終わりで、Sample7からはStyleについて解説していきます。しかしながら、今後ControlTemplateの開発を行ったり、勉強を進める上で必要になる内容が残っています。以降の項目に掲載します。
Button以外のコントロールの構成要素
Buttonコントロールが本来持つ構成要素がContentPresenterであったことのように、他の様々なコントロールがどのような構成であるかを知らなければ、ControlTemplateの設計、外観のデザインは困難です。またTrigger(トリガー)についても同様で、どのようなイベント(トリガー)がコントロール上で検知されるのかを把握しなければ、やはり設計やデザインはできません。
私の調査不足もあるのかもしれませんが、公式にはmsdn(VisualStudio)にわずかに掲載されている情報しかないと思います。そしてこの資料を作るきっかけとなったように、それは非常にわかりにくい内容となっています(2013.04.14現在)。なぜ分かりにくいのかというと、対象のコントロールが正規に持っている構成要素のみを示した情報がないからです。
例えばここに示したページから"ボタンのスタイルとテンプレート"のページに移動すると、Buttonに設定することのできるTrigger(のイベント)の例になるであろう"表示状態の一覧"と、コントロールテンプレートを編集した例が掲載されています。このページの最終更新時点では、Triggerに設定できる正確な条件の一覧は掲載されていませんし、コントロールテンプレートの例も、複合的で分かりにくいものとなっています。
あるいは公式では次のページも役に立つかもしれません。ContentPresenterのように、ItemPresenterやTickBarといった、一般的なアプリケーション開発では触れることのない特殊な構成要素(コントロール)がどのコントロールであつかわれているかを確認することができます。
(2013.04.14)現在、コントロールの構成要素などを知るための最も良い方法は、"WPF Inspector"を利用することだと思われます。構成要素を閲覧するためのLogicalTreeの表示が可能であるため、ControlTemplateなどの開発に大いに利用することができるはずです。