为何选择RelayCommand

Kro*_*owi 44 c# wpf binding mvvm 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

Roh*_*ats 72

命令用于分离语义和从执行命令的逻辑调用命令的对象,即它将UI组件与需要在命令调用上执行的逻辑分开.因此,您可以使用测试用例单独测试业务逻辑,并且您的UI代码与业务逻辑松散耦合.

现在,那就是让我们逐一挑选你的问题:

它做了什么工作?

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


它可用于表单中的所有命令吗?

一些控件暴露了Command DependencyProperty,如Button,MenuItem等,它们都注册了一些默认事件.对于Button它的Click事件.因此,如果ICommand使用Button的Command DP在ViewModel中声明绑定,则只要单击按钮,就会调用它.

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


如果(a)某些文本框未填写,如何禁用该按钮?

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

CanExecute如果任何绑定属性为null或为空,它会自动禁用绑定到哪个命令的控件,则在ViewModel和委托中绑定TextBox并返回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
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的解释和例子,它是如何完成的,但恐怕还是有点困惑。我曾经在 C# 中编程,但为了学校而不得不切换到 VB.NET,所以这不是问题,但是,我现在如何链接命令并说明它在我的视图模型中必须做什么,例如显示“MessageBox”与“文本框”的内容 (2认同)
  • 我刚刚在 youtube 上观看了这个视频,https://www.youtube.com/watch?v=ysWK4e2Mtco,在`19:30` 他建议不要使用 CommandManager.RequerySuggested (2认同)
  • 小问题:微软建议避免使用`Predicate&lt;T&gt;`,而使用`Func&lt;T, bool&gt;`。 (2认同)

Den*_*sel 5

使用relay命令的好处是您可以将命令直接绑定到ViewModel.通过以这种方式使用命令,您可以避免在视图代码隐藏中编写代码.

使用中继命令时,您必须提供两种方法.第一个提供一个值是否可以执行命令(例如"CanExecuteSave"),而另一个将负责执行命令("ExecuteSave").