ICommand在Mvvm中的原因是什么?

时间:2017-02-08 12:39:20

标签: c# wpf mvvm icommand

在使用mvvm方法的应用程序中,ViewModel提供一个或多个 Command -properties非常常见。这些属性通常具有 ICommand DelegateCommand 等类型。

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

为什么ICommand存在?

4 个答案:

答案 0 :(得分:8)

  

提供公共方法并绑定操作是不够的   从直接看到这个公共方法?为什么ICommand存在?

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

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

  3. 这是一种常见的模式,可以使用不同的参数调用该命令。
  4. 普通的事件处理程序不符合这些要求,但ICommand服务器完全符合这些目的:

    public interface ICommand
    {
        void Execute(object parameter);
        bool CanExecute(object parameter);
        event EventHandler CanExecuteChanged;
    }
    
    1. 它将方法包装到对象
    2. 它表示命令是否可用,因此UI组件(通常是按钮或menuitem)可以反映它
    3. 此外,它通知UI组件命令的可用性已更改,因此UI可以反映它。
    4. 现在,让我们考虑复制和粘贴方案。使用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

      那么优雅

答案 1 :(得分:2)

  

提供公共方法并将视图中的操作直接绑定到此公共方法是否足够?

如果点击视图中的Button,您将如何调用公共方法?

答案是您将Command的{​​{1}}属性绑定到为您调用方法的视图模型的Button属性。这是查看模型定义的任何操作使用命令公开的主要原因。

命令只是一个实现ICommand接口的对象,并封装了要执行的操作的代码。

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

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

答案 2 :(得分:1)

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

在MFC中,您刚刚注册了一个事件处理程序(在WPF中仍然可以),但在MVVM中,可以只绑定一个ICommand,而不是触发事件。

答案 3 :(得分:0)

简短: 例如纽扣 按钮通过创建由方法组成的事件(Click =“ XEvent”)起作用,然后我们告诉应用程序下一步该怎么做,即,调用其他明显与Code配合的方法。 (事件=>方法在MainWindow.xaml.cs处生成。)

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

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

好吧,ICommand接口可以有其他选择,例如将ViewModel中的方法绑定到XAML中的命令(不过,首选) 这里

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

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