c# – 在Mvvm中ICommand的原因是什么?

在使用mvvm方法的应用程序中,ViewModel提供一个或多个Command属性是很常见的.这些属性通常具有ICommand或DelegateCommand类型或类似的类型.

我不明白为什么我们在mvvm应用程序中需要这样的方法.提供公共方法并将视图中的操作直接绑定到此公共方法是不够的?

为什么ICommand存在?

最佳答案

Wouldn’t it be enough to provide public methods and bind the action
from the view directly to this public method? Why ICommand exists?

>您无法绑定到xaml中的方法.你需要一个物体.因此,您需要将方法包装到对象.
>它是UI中的常见模式,某些操作始终不可用.在登录表单中,只有在输入用户名时,“登录”操作才可用.在MS Word中,只有在您选择某些内容时,“复制”或“剪切”操作才可用,否则按钮将被禁用,键盘快捷键将处于非活动状态
>这是一种常见模式,可以使用不同的参数调用该命令.

普通的事件处理程序不符合这些要求,但ICommand服务器完全符合以下目的:

public interface ICommand
{
    void Execute(object parameter);
    bool CanExecute(object parameter);
    event EventHandler CanExecuteChanged;
}

>它将方法包装到对象
>它表示命令是否可用,因此UI组件(通常是按钮或menuitem)可以反映它
>此外,它通知UI组件命令的可用性已更改,因此UI可以反映它.

现在,让我们考虑复制和粘贴方案.使用ICommand标记可能如下所示:

<Button Content="Paste" Command="{Binding PasteCommand}" />
<MenuItem Header="Paste" Command="{Binding PasteCommand}" />
public ICommand PasteCommand {get;} = new DelegateCommand(Paste, () => Clipboard != null);

没有ICommand会怎么样?为了简化,我们考虑一下,XAML允许绑定到方法:

<Button Content="Paste" Click="{Binding Paste}" IsEnabled="{Binding CanPaste}" />
<MenuItem Header="Paste" Click="{Binding Paste}" IsEnabled="{Binding CanPaste}"/>

public void Paste() {....}

private bool _canPaste;
public bool CanPaste
{
    get { return _canPaste }
    set 
    { 
        if (_canPaste != value)
        {
            _canPaste = value;
            OnNotifyPropertyChanged(nameof(CanPaste);
        }
    }
}

正如你所看到的,它不仅更加冗长,而且还违反了DRY原则.每次要使用该命令时,都需要指定Paste和CanPaste绑定.如果您在没有CanPaste的情况下开始,之后又想添加它,该怎么办?然后,您必须在每次粘贴调用时添加CanPaste绑定.我向你保证,你会在某个地方忘记它.

现在,如果你在WPF中这样做了:

<Button Content="Paste" Click="Call_ViewModel_Paste" />

 

//in codebehind:
void Call_ViewModel_Paste(oobject sender, RoutedEventArgs e)
{
    ViewModel.Paste();
}

或者最终:

<Button Content="Paste">
     <i:Interaction.Triggers>
         <i:EventTrigger EventName="Click">
             <ei:CallMethodAction MethodName="Paste" TargetObject="{Binding}"/>
         </i:EventTrigger>
     </i:Interaction.Triggers>
</Button>

这两种方法都是正确的,它们遵循MVVM原则而无需ICommand工作,但正如您所看到的,它们都不像ICommand那样优雅

转载注明原文:c# – 在Mvvm中ICommand的原因是什么? - 代码日志