web-dev-qa-db-ja.com

RelayCommandを使用する理由

私は最近WPFで多くのプログラミングを行ってきましたが、この時点でViewとViewModelは分離されていません。まあ、それは部分的にです。テキストボックス内のテキスト、ラベルのコンテンツ、データグリッド内のリストなどに関係するすべてのバインディングは、NotifyPropertyChangedイベントを含む通常のプロパティによって実行されます。

ボタンのクリックやテキストの変更を処理するためのすべてのイベントは、イベントをリンクすることによって行われます。今、私はコマンドの操作を開始したかったし、この記事を見つけました: http://www.codeproject.com/Articles/126249/MVVM-Pattern-in-WPF-A-Simple-Tutorial-for-Absolute 。 MVVMのセットアップ方法の説明がありますが、RelayCommandと混同しています。

どんな仕事をしているの?フォーム内のすべてのコマンドに使用できますか? (a)特定のテキストボックスが入力されていないときにボタンを無効にするにはどうすればよいですか?


編集1:

「フォーム内のすべてのコマンドに使用可能ですか?」に対する適切な説明ここで回答されています: https://stackoverflow.com/a/22286816/3357699

ここに私がこれまでに持っているコードがあります: https://stackoverflow.com/a/22289358/3357699

40
Krowi

コマンドは、セマンティクスと、コマンドを実行するロジックからコマンドを呼び出すオブジェクトを分離するために使用されます。つまり、UIコンポーネントを必要なロジックから分離します。コマンド呼び出しで実行されます。そのため、テストケースを使用してビジネスロジックを個別にテストでき、UIコードはビジネスロジックに疎結合されます。

さて、あなたの質問を一つ一つ選んでみましょう。

どんな仕事をしているの?

上記の詳細を追加しました。コマンドの使用法がクリアされることを願っています。


フォームのすべてのコマンドに使用できますか?

一部のコントロールは、Button、MenuItemなど、Command DependencyPropertyを公開しています。これらには、いくつかのデフォルトイベントが登録されています。 Buttonの場合は、Clickイベントです。したがって、ViewModelで宣言されたICommandをButtonのCommand DPにバインドすると、ボタンがクリックされるたびに呼び出されます。

他のイベントについては、Interactivity triggersを使用してバインドできます。サンプルを参照してください here ViewModelでICommandにバインドするためにそれらを使用する方法。


(a)特定のテキストボックスが入力されていないときにボタンを無効にするにはどうすればよいですか?

投稿したリンクは、RelayCommandの完全な実装を提供していません。コマンドがバインドされるUIコントロールの有効化/無効化で重要な役割を果たすCanExecute述語を設定するオーバーロードコンストラクターがありません。

ViewModelおよびCanExecuteデリゲートの一部のプロパティでTextBoxをバインドすると、バインドされたプロパティのいずれかがnullまたは空の場合にfalseが返され、コマンドがバインドされるコントロールが自動的に無効になります。


RelayCommandの完全な実装:

public class RelayCommand<T> : ICommand
{
    #region Fields

    readonly Action<T> _execute = null;
    readonly Predicate<T> _canExecute = null;

    #endregion

    #region Constructors

    /// <summary>
    /// Initializes a new instance of <see cref="DelegateCommand{T}"/>.
    /// </summary>
    /// <param name="execute">Delegate to execute when Execute is called on the command.  This can be null to just hook up a CanExecute delegate.</param>
    /// <remarks><seealso cref="CanExecute"/> will always return true.</remarks>
    public RelayCommand(Action<T> execute)
        : this(execute, null)
    {
    }

    /// <summary>
    /// Creates a new command.
    /// </summary>
    /// <param name="execute">The execution logic.</param>
    /// <param name="canExecute">The execution status logic.</param>
    public RelayCommand(Action<T> execute, Predicate<T> canExecute)
    {
        if (execute == null)
            throw new ArgumentNullException("execute");

        _execute = execute;
        _canExecute = canExecute;
    }

    #endregion

    #region ICommand Members

    ///<summary>
    ///Defines the method that determines whether the command can execute in its current state.
    ///</summary>
    ///<param name="parameter">Data used by the command.  If the command does not require data to be passed, this object can be set to null.</param>
    ///<returns>
    ///true if this command can be executed; otherwise, false.
    ///</returns>
    public bool CanExecute(object parameter)
    {
        return _canExecute == null ? true : _canExecute((T)parameter);
    }

    ///<summary>
    ///Occurs when changes occur that affect whether or not the command should execute.
    ///</summary>
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    ///<summary>
    ///Defines the method to be called when the command is invoked.
    ///</summary>
    ///<param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to <see langword="null" />.</param>
    public void Execute(object parameter)
    {
        _execute((T)parameter);
    }

    #endregion
}
65
Rohit Vats

Relayコマンドを使用する利点は、コマンドをViewModelに直接バインドできることです。このような方法でコマンドを使用すると、ビューのコードビハインドでコードを書くことを避けられます。

リレーコマンドを使用する場合、2つの方法を提供する必要があります。最初のものはコマンドを実行できるかどうかの値を提供し(例:「CanExecuteSave」)、もう1つはコマンドの実行を担当します(「ExecuteSave」)。

4
Dennis Kassel