Silverlight3にCommandを――

Silverlight3 では Button に Command プロパティが無いので、コマンドオブジェクトをバインドできない。Silverlight3 で MVVM パターンをやろうと思うと、そこが障害になる。

Button の Click イベントハンドラ内でコマンドを直接実行しても疎結合にはできるけど、イベントハンドラが大量生産されるので嫌。コマンドのためだけに、以前紹介したサードパーティのライブラリを使うのも大袈裟。

だから、私は添付ビヘイビアを自作している。

public static class CommandBehavior
{
    public static readonly DependencyProperty CommandProperty = DependencyProperty.RegisterAttached(
        "Command",
        typeof(ICommand),
        typeof(CommandBehavior),
        new PropertyMetadata(null, OnCommandPropertyChanged));

    public static void SetCommand(DependencyObject target, ICommand command)
    {
        target.SetValue(CommandProperty, command);
    }

    public static ICommand GetCommand(DependencyObject target)
    {
        return target.GetValue(CommandProperty) as ICommand;
    }

    private static void OnCommandPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        // Button や HyperlinkButton で Command が使えるようにする
        ButtonBase button = sender as ButtonBase;
        if (button != null)
        {
            ICommand command = e.NewValue as ICommand;
            if (command != null)
            {
                button.Click += ButtonBaseClick;
            }
            else
            {
                button.Click -= ButtonBaseClick;
            }
            return;
        }
    }

    private static void ButtonBaseClick(object sender, RoutedEventArgs e)
    {
        // 添付プロパティで指定されたコマンドを実行
        ButtonBase button = sender as ButtonBase;
        ICommand command = GetCommand(button);
        command.Execute(button.Tag);
    }
}
<Button Content="コピー"
        sample:CommandBehavior.Command="{Binding Path=CopyCommand}"/>

Silverlight4 からはコマンドがサポートされるので、この添付ビヘイビアはそれまでのつなぎ。だから、WPF のコマンドみたいに CanExecute の結果をチェックして、自動で Button の有効・無効を切り替える機能は実装していない。

現時点で Silverlight4 はまだベータか。早く正式リリースされないかな。