Silverlight の DateTemplate に DataType が無い!

WPF だと、 MVVM パターンで ViewModel と View を結びつけるときに、DataTemplate を使って次のように書けます。

<DataTemplate x:Key="SampleViewModel" DataType="{x:Type SampleViewModel}">
    <vw:SampleView />
</DataTemplate>

しかし、Silverlight の DataTemplate には DataType が無い!

<!-- DataType を指定できない! -->
<DataTemplate x:Key="SampleViewModel">
    <vw:SampleView />
</DataTemplate>

DataType が無いので、例えば

  • FooViewModel をバインドしたときは FooView を表示する
  • BarViewModel をバインドしたときは BarView を表示する

といった View の切り替え処理を実現するのにも一手間。Content 変更時に Content の型をチェックして、ContentTemplate を変更するしかありません。

ContentControl には ContentChanged イベントが無いですが、protected な OnContentChanged メソッドは用意されています。次のように ContentControl を拡張すればいい。

public class ContentChangedEventArgs : EventArgs
{
    public object OldContent { get; private set; }
    public object NewContent { get; private set; }
    public ContentChangedEventArgs(object oldContent, object newContent)
    {
        OldContent = oldContent;
        NewContent = newContent;
    }
}

public class MyContentControl : ContentControl
{
    public event EventHandler<ContentChangedEventArgs> ContentChanged;

    protected override void OnContentChanged(object oldContent, object newContent)
    {
        base.OnContentChanged(oldContent, newContent);

        var handler = ContentChanged;
        if (handler != null)
        {
            handler(this, new ContentChangedEventArgs(oldContent, newContent));
        }
    }
}

ContentControl の代わりにこのクラスを使えば、View にイベントで Content の変更を伝えることが可能です。

しかし、なんで ContentChanged イベントが用意されていないんだろう?不親切ですよね。