かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

PrismのDelegateCommandのかわり

Prismに不満はないようなあるような感じの今日この頃です。DelegateCommandのCanExecuteChangedイベントは自分で明示的に発生させないといけない作りになってたりします。Silverlightなら、CommandManagerがいないからそれでもいいんだけど、WPFだとCommandManagerという便利なクラスがあるので、そちらを使う方がお得な気がします。

なんか前にも同じようなコード書いた気がするけど、Prismを採用するときのための自前のCommandクラスのコードを貼っておきます。

// non generic版
public class RelayCommand : ICommand
{
    private Action execute;
    private Func<bool> canExecute;

    public RelayCommand(Action execute, Func<bool> canExecute)
    {
        if (execute == null)
        {
            throw new ArgumentNullException("execute");
        }

        if (canExecute == null)
        {
            throw new ArgumentNullException("canExecute");
        }

        this.execute = execute;
        this.canExecute = canExecute;
    }

    public RelayCommand(Action execute)
        : this(execute, () => true)
    {
    }

    public void Execute()
    {
        this.execute();
    }

    public bool CanExecute()
    {
        return this.canExecute();
    }

    bool ICommand.CanExecute(object parameter)
    {
        return this.CanExecute();
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    void ICommand.Execute(object parameter)
    {
        this.execute();
    }
}
// generic版
public class RelayCommand<T> : ICommand
{
    private Action<T> execute;
    private Func<T, bool> canExecute;

    public RelayCommand(Action<T> execute, Func<T, bool> canExecute)
    {
        if (execute == null)
        {
            throw new ArgumentNullException("execute");
        }

        if (canExecute == null)
        {
            throw new ArgumentNullException("canExecute");
        }

        this.execute = execute;
        this.canExecute = canExecute;
    }

    public RelayCommand(Action<T> execute)
        : this(execute, p => true)
    {
    }

    public void Execute(T parameter)
    {
        this.execute(parameter);
    }

    public bool CanExecute(T parameter)
    {
        return this.canExecute(parameter);
    }

    bool ICommand.CanExecute(object parameter)
    {
        if (parameter == null)
        {
            return this.CanExecute(default(T));
        }

        return this.CanExecute((T)parameter);
    }

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    void ICommand.Execute(object parameter)
    {
        if (parameter == null)
        {
            this.Execute(default(T));
            return;
        }

        this.execute((T)parameter);
    }
}

以上!今日はモチベーションが上がらないですわ。