かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

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);
    }
}

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