在 MVVM 中指挥

命令用于在尊重 MVVM 模式的同时处理 WPF 中的 Events

正常的 EventHandler 看起来像这样(位于 Code-Behind):

public MainWindow()
{
    _dataGrid.CollectionChanged += DataGrid_CollectionChanged;
}

private void DataGrid_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
        //Do what ever
}

不能在 MVVM 中使用 Commands

 <Button Command="{Binding Path=CmdStartExecution}" Content="Start" />

我建议为命令属性使用某种前缀(Cmd),因为你将主要在 xaml 中使用它们 - 这样它们更容易识别。

因为它是 MVVM,你想要在你的 ViewModel 中处理那个命令(对于 Button``eq``Button_Click)。

为此,我们基本上需要两件事:

  1. System.Windows.Input.ICommand
  2. RelayCommand(例如从这里获取)

一个简单的例子可能如下所示:

private RelayCommand _commandStart;
public ICommand CmdStartExecution
{
   get
   {
      if(_commandStart == null)
      {
          _commandStart = new RelayCommand(param => Start(), param => CanStart());
      }
      return _commandStart;
   }
}

public void Start()
{
   //Do what ever
}

public bool CanStart()
{
    return (DateTime.Now.DayOfWeek == DayOfWeek.Monday); //Can only click that button on mondays.
}

那么这个细节是做什么的:

ICommand 是 xaml 中的 Control 所绑定的。RelayCommand 将你的命令发送到 Action(即调用 Method)。Null-Check 只确保每个 Command 只会初始化一次(由于性能问题)。如果你已经阅读了上面 RelayCommand 的链接,你可能已经注意到 RelayCommand 对于它的构造函数有两个重载。(Action<object> execute)(Action<object> execute, Predicate<object> canExecute)

这意味着你可以(通常)添加第二个 Method 返回一个 bool 来告诉 Control whehe事件可以发射或不发射。

一个好处是,如果 Method 将返回 false,例如 Buttons 将是 false

CommandParameters

<DataGrid x:Name="TicketsDataGrid">
    <DataGrid.InputBindings>
        <MouseBinding Gesture="LeftDoubleClick" 
                      Command="{Binding CmdTicketClick}" 
                      CommandParameter="{Binding ElementName=TicketsDataGrid, 
                                                 Path=SelectedItem}" />
    </DataGrid.InputBindings>
<DataGrid />

在这个例子中,我想将 DataGrid.SelectedItem 传递给我的 ViewModel 中的 Click_Command。

你的方法应如下所示,而 ICommand 实现本身保持如上所述。

private RelayCommand _commandTicketClick;

public ICommand CmdTicketClick
{
   get
   {
       if(_commandTicketClick == null)
       {
           _commandTicketClick = new RelayCommand(param => HandleUserClick(param));
       }
       return _commandTicketClick;
   }
}

private void HandleUserClick(object item)
{
    MyModelClass selectedItem = item as MyModelClass;
    if (selectedItem != null)
    {
        //Do sth. with that item
    }
}