繁体   English   中英

Mvvm中ICommand的原因是什么?

[英]What is the reason for ICommand in Mvvm?

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

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

为什么 ICommand 存在?

提供公共方法并将视图中的操作直接绑定到此公共方法还不够吗? 为什么 ICommand 存在?

  1. 您不能绑定到 xaml 中的方法。 你需要一个对象。 因此,您需要将该方法包装到一个对象中。

  2. 这是 UI 中的一种常见模式,即某些操作并非始终可用。 在登录表单中,登录操作仅在您输入用户名时才可用。 在 MS Word 中,复制或剪切操作仅在您选择某些内容时才可用,否则按钮将被禁用且键盘快捷键处于非活动状态

  3. 这是一种常见的模式,可以使用不同的参数调用该命令。

普通的事件处理程序不满足这些要求,但ICommand正是为了这些目的:

public interface ICommand
{
    void Execute(object parameter);
    bool CanExecute(object parameter);
    event EventHandler CanExecuteChanged;
}
  1. 它将方法包装到一个对象
  2. 它表示命令是否可用,因此 UI 组件(通常是按钮或菜单项)可以反映它
  3. 此外,它会通知 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 原则。 每次要使用该命令时,都需要指定PasteCanPaste绑定。 如果您开始时没有使用 CanPaste,后来又想添加它,该怎么办? 然后您必须在每次出现Paste调用时添加 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优雅

提供公共方法并将视图中的操作直接绑定到此公共方法还不够吗?

例如,当单击视图中的Button时,您将如何调用公共方法?

答案是您将ButtonCommand属性绑定到为您调用该方法的视图模型的ICommand属性。 这是视图模型定义的任何操作都使用命令公开的主要原因。

命令只不过是一个对象,它实现了System.Windows.Input.ICommand接口并封装了要执行的操作的代码。

有关该概念的更多信息,请参阅以下链接。

https://blog.magnusmontin.net/2013/06/30/handling-events-in-an-mvvm-wpf-application/ https://msdn.microsoft.com/en-us/magazine/dn237302.aspx

在 MVVM 中,您尝试避免“代码隐藏”(这是 MyView.cs 文件中的代码)以避免 View、ViewModel 和 Model 的紧密耦合。

在 MFC 中,您刚刚注册了一个事件处理程序(这在 WPF 中仍然是可能的),但在 MVVM 中,有可能只绑定一个 ICommand,该 ICommand 将被执行而不是触发事件。

简短:例如。 按钮 按钮的工作原理是创建由方法组成的事件(Click="XEvent"),然后我们告诉应用程序接下来要做什么,即调用其他明显与代码一起工作的方法。 (事件 => 方法在MainWindow.xaml.cs生成。)

在 MVVM 中,我们避免了模式背后的代码。 为了实现这一点,我们需要将 DataContext 设置为其他类(将充当中间件),比如MainWindowViewModel.cs

通过实现 ICommand 接口和实现处理命令的方法,我们避免了维护 MVVM 模式的代码。

那么可以有 ICommand 接口的替代方案,例如将 ViewModel 中的方法绑定到 XAML 中的命令(尽管不喜欢)here

<Button Command="{ViewModel AnyMethodName}"/>

PLUS ICommand 接口将为您提供 CanExecute 方法,该方法可用于启用/禁用控制器简单委托不会为您提供该功能希望这会有所帮助:)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM