Silverlight 2 Betaのコントロールテンプレートモデルに関する是非
Silverlight 2 Betaのコントロールテンプレートモデルに関する以下の投稿が非常に興味深いと思いました。
I Like the Silverlight 2.0 Control Templating Model (better than WPF’s)
関連リンク:スタイルの設定が可能なコントロールを設計するためのガイドライン
http://designerslove.net/?p=168
http://devlicio.us/blogs/rob_eisenberg/archive/2008/03/13/there-s-some-darkness-in-your-silver-light.aspx
The BIG Problem with Silverlight's Control Templating Model
関連リンク:Introduction to Model/View/ViewModel pattern for building WPF apps – Tales from the Smart Client
前回の投稿でロパティトリガが存在しないことは影響が大きいと書きましたが、これらの内容はまさにそれに起因するものだと思います。では、プロパティトリガがないことでコントロールのテンプレートを作成する際にどのような問題がでてくるのか、実際に見ていきたいと思います。
例として、非常にシンプルなButtonコントロールのテンプレートにEllipseを使った丸いボタンを使います。このボタン色は通常は赤ですが、マウスカーソルがボタンの上にくると青に変化します。
WPFの場合下記のようなXAMLになります。
<Setter Property="Background" Value="Red"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Ellipse Fill="{TemplateBinding Background}"/>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="Blue"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Silverlight 2 Betaの場合下記のようなXAMLになります。
<Setter Property="Background" Value="Red" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="RootElement">
<Grid.Resources>
<Storyboard x:Key="Normal State" />
<Storyboard x:Key="MouseOver State">
<ColorAnimation Duration="0:0:0.001" Storyboard.TargetName="BaseEllipse" Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" To="Blue" />
</Storyboard>
</Grid.Resources>
<Ellipse x:Name="BaseEllipse" Fill="{TemplateBinding Background}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
WPFの場合、プロパティトリガを使いIsMouseOverプロパティ値がtrueのときにはBackgroundプロパティをBlueに設定されるように宣言しています。非常にシンプルです。
Silverlight 2 Betaではプロパティトリガが使えないので、ストーリーボードを使ってEllispeのFillプロパティをBlueに変化させています。ではこのストーリーボードが実行される処理はどこに書いてあるのでしょうか?これは実はXAMLではなくコードで書かれています。そのために、テンプレートのルート要素のKeyが"RootElement"という名称であることと、さらにマウスオーバー時に実行させたいストーリーボードのKeyが"MouseOver State"であることは非常に重要です。
Silverlight 2 BetaのButtonクラスには以下のように6つものTemplatePart属性が付けられています。
[TemplatePart(Name = Button.ElementFocusVisualName, Type = typeof(UIElement))]
[TemplatePart(Name = Button.StateNormalName, Type = typeof(Storyboard))]
[TemplatePart(Name = Button.StateMouseOverName, Type = typeof(Storyboard))]
[TemplatePart(Name = Button.StatePressedName, Type = typeof(Storyboard))]
[TemplatePart(Name = Button.StateDisabledName, Type = typeof(Storyboard))]
public class Button : ButtonBase
このことが表しているように、Silverlight 2 BetaのButtonコントロールのコードは、これらの要素が存在していることが前提のロジックが記述されています。
どういうコードかというと、"RootElement"という要素を探しそこから見つけた"MouseOver State"というストーリーボードをマウスオーバー時に実行するというコードです。
これらのことからWPFとSilverlight 2 Betaのテンプレートモデルには大きな違いが生まれています。それは、WPFがビューに関することはXAMLだけで完結しているのに対し、Silverlight 2 Betaではビューのためのインタラクションであってもそれはコードを記述する必要があるということです。
同じように書けるのに同じには書けない、それがWPFとSilverlightといった感じです。