一尘不染

为什么要使用RelayCommand

c#

我最近在WPF中进行了很多编程,但此时我的View和ViewModel尚未分开。好吧,这是部分的。我所有与文本框中的文本,标签的内容,数据网格中的列表等有关的绑定都是由常规属性(其中带有NotifyPropertyChanged事件)完成的。

我所有用于处理按钮单击或文本更改内容的事件都是通过链接事件来完成的。现在,我想开始使用命令并找到本文:http :
//www.codeproject.com/Articles/126249/MVVM-Pattern-in-WPF-A-Simple-Tutorial-
for-Absolute。它解释了如何设置MVVM,但是我对MVVM感到困惑RelayCommand

它做什么工作?它可以用于表单中的所有命令吗?当未填写某些文本框时,如何使按钮禁用?


编辑1:

一个很好的解释:“它可以用于表单中的所有命令吗?”
在这里得到回答:https :
//stackoverflow.com/a/22286816/3357699

这是我到目前为止的代码:https :
//stackoverflow.com/a/22289358/3357699


阅读 1010

收藏
2020-05-19

共1个答案

一尘不染

命令用于 将语义和调用命令的对象与执行命令
的逻辑分开,即,将UI组件与需要在命令调用时执行的逻辑分开。因此,您可以使用测试用例分别测试业务逻辑,并且您的UI代码可以松散地耦合到业务逻辑。

话虽如此,让我们一个接一个地选择您的问题:

它做什么工作?

我已在上面添加了详细信息。希望它清除命令的用法。


它可以用于我表格中的所有命令吗?

一些控件公开了Command
DependencyProperty,如Button,MenuItem等,这些控件已注册了一些默认事件。对于Button,这是Click事件。因此,如果将ICommandViewModel中声明的内容与Button的Command
DP 绑定,则只要单击button就会调用它。

对于其他事件,可以使用绑定Interactivity triggers。请参阅此处的示例了解如何ICommand在ViewModel中使用它们进行绑定。


当未填写某些文本框时,如何使按钮禁用?

您发布的链接未提供的完整实现RelayCommand。它缺少设置CanExecute谓词的重载构造函数,该谓词在启用/禁用命令绑定到的UI控件中起着关键作用。

CanExecute如果任何绑定的属性为null或为空,则将TextBoxes与ViewModel和委托中的某些属性绑定将返回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
}
2020-05-19