5

私のプロジェクトでは、MVVM (& コマンド) を使用したいと思います。コマンドと ICommand の実装について学び始めました。

パラメータなしの実装を作成したいと思いICommandます。 (データのロード/データのフラッシュなどをトリガーするには-パラメーターは必要ないので、パラメーターなしでコマンドを作成しようとするのは自然なようです)

これは私が使用しているコードです:

using System.Windows.Input;

public class NoParameterCommand : ICommand
{
    private Action executeDelegate = null;
    private Func<bool> canExecuteDelegate = null;
    public event EventHandler CanExecuteChanged = null;

    public NoParameterCommand(Action execute)
    {
        executeDelegate = execute;
        canExecuteDelegate = () => { return true; };
    }
    public NoParameterCommand(Action execute, Func<bool> canExecute)
    {
        executeDelegate = execute;
        canExecuteDelegate = canExecute;
    }

    public bool CanExecute()
    {
        return canExecuteDelegate();
    }
    public void Execute()
    {
        if (executeDelegate != null)
        {
            executeDelegate();
        }
    }
}

しかし、ICommand インターフェイスを正しい方法で実装していないというエラーが発生しました ( 'XXX.YYYY.NoParameterCommand' does not implement interface member 'System.Windows.Input.ICommand.Execute(object)')

そこで、代わりに次のようにすることを考えました。

CanExecute(およびに欠落していたパラメータを追加Execute)

public class NoParameterCommand : ICommand
{
    ...omitted - no changes here...

    public bool CanExecute(object parameter) //here I added parameter
    {
        return canExecuteDelegate();
    }
    public void Execute(object parameter)    //and here
    {
        if (executeDelegate != null)
        {
            executeDelegate();
        }
    }
}
  1. これは良い方法ですか?
  2. 別の方法を使用する必要がありますか? (そうであれば、代わりに何をすべきですか?)
4

3 に答える 3

7
  1. これは良い方法です。
  2. いいえ、別の方法を使用しないでください。

追加の提案:

これについてもう一度考えてみると、追加の階層レベル whereCanExecute()Execute()areを導入してアーキテクチャを改善しますabstract。そのクラスから、デリゲートを呼び出すコマンド クラスを派生させます。

このようにして、デリゲートを介してパラメーターなしのコマンドにロジックを提供するか、基本コマンド クラスをサブクラス化するかを後で決定できます。

于 2013-10-14T12:41:24.330 に答える
5

あなたの懸念が何なのかよくわかりません。ICommandインターフェイスのパラメーターを無視するのが一般的です。

パラメーターを持たないメソッドが本当に必要な場合はCanExecute、 (暗黙的にではなく) 明示的にインターフェイスを実装できます。メソッドは引き続き存在しますが、外部からオブジェクトを見ている人には、それらのメソッドを見ることができませんExecuteICommand

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

public bool CanExecute()
{
  //do work
}

基本的にインターフェースの実装を隠しています。誰かがCanExecuteインターフェイスからメソッドを直接呼び出したい場合は、それを行うために型キャストするICommand必要があります。このようにしても実際には何も得られませんが、クラスが外部の開発者にどのように見えるかを気にしている場合 (たとえば、API を開発している場合) は、クラスを少しきれいに見せることができます。パラメータは必要ありません。

于 2013-10-14T12:47:06.473 に答える
2

私は個人的にこの方法を好みます:

public class MyCommand : ICommand
{
    private static bool True() { return true; }

    private readonly Action _execute;
    private Func<bool> _canExecute;
    private Func<bool> _isVisible;

    public event EventHandler IsVisibleChanged;
    public event EventHandler CanExecuteChanged;

    public MyCommand(Action execute, Func<bool> canExecute = null, Func<bool> isVisible = null)
    {
        _execute = execute;
        _canExecute = canExecute ?? True;
        _isVisible = isVisible ?? True;
    }

    public void Execute()
    {
        _execute();
    }

    public Func<bool> CanExecute
    {
        set
        {
            _canExecute = value ?? True;
            CanExecuteChanged(this, new EventArgs());
        }
        get { return _canExecute; }
    }

    public Func<bool> IsVisible
    {
        set
        {
            _isVisible = value ?? True;
            IsVisibleChanged(this, new EventArgs());
        }
        get { return _isVisible; }
    }

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

    void ICommand.Execute(object parameter)
    {
        Execute();
    }
}

ただし、デリゲートは通常変更されないため、不変バージョンを好みます。

[ImmutableObject(true)]
public class MyImmutableCommand : ICommand
{
    private static bool True() { return true; }

    private readonly Action _execute;
    private readonly Func<bool> _canExecute;
    private readonly Func<bool> _isVisible;

    [Obsolete("Will not be invoked, because the implementation never changes.")]
    public event EventHandler CanExecuteChanged;

    public MyImmutableCommand(Action execute, Func<bool> canExecute = null, Func<bool> isVisible = null)
    {
        _execute = execute;
        _canExecute = canExecute ?? True;
        _isVisible = isVisible ?? True;
    }

    public bool CanExecute()
    {
        return _canExecute(); 
    }

    public bool IsVisible()
    {
        return _isVisible(); 
    }

    public void Execute()
    {
        _execute();
    }

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

    void ICommand.Execute(object parameter)
    {
        Execute();
    }
}
于 2014-12-07T12:16:58.553 に答える