我最近在 WPF 中进行了大量编程,但此时我的 View 和 ViewModel 并没有分开。好吧,这是部分的。我所有与文本框中的文本、标签内容、数据网格中的列表等相关的绑定(bind)都是由带有 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
最佳答案
命令用于将调用命令的语义和对象与执行命令的逻辑分开,即将 UI 组件与需要在命令调用时执行的逻辑分开。因此,您可以使用测试用例单独测试业务逻辑,而且您的 UI 代码与业务逻辑松耦合。
现在,话虽如此,让我们一一挑选您的问题:
What job does it do?
我已经在上面添加了详细信息。希望它清除了命令的用法。
Is it usable for all commands in my form?
一些控件公开了 Command DependencyProperty,例如 Button、MenuItem 等,其中注册了一些默认事件。对于 Button,它是 Click
事件。因此,如果您将在 ViewModel 中声明的 ICommand
与 Button 的 Command DP 绑定(bind),则只要单击按钮,就会调用它。
对于其他事件,您可以使用交互触发器
进行绑定(bind)。引用样本here如何使用它们绑定(bind)到 ViewModel 中的 ICommand
。
How do I make the button disable when (a) certain text box(es) are not filled in?
您发布的链接未提供 RelayCommand
的完整实现。它缺少用于设置 CanExecute
谓词的重载构造函数,该谓词在启用/禁用您的命令绑定(bind)到的 UI 控件中起着关键作用。
使用 ViewModel
和 CanExecute
中的某些属性绑定(bind) TextBox
委托(delegate)返回 false
如果任何绑定(bind)属性为 null
或空,这会自动禁用命令绑定(bind)到的控件。
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 || _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
}
关于c# - 为什么选择 RelayCommand,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22285866/