gpt4 book ai didi

c# - 为什么选择 RelayCommand

转载 作者:IT王子 更新时间:2023-10-29 03:57:29 24 4
gpt4 key购买 nike

我最近在 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

这是我目前的代码:https://stackoverflow.com/a/22289358/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 notfilled in?

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

使用 ViewModelCanExecute 中的某些属性绑定(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/

24 4 0