在 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)。
为此,我们基本上需要两件事:
- System.Windows.Input.ICommand
- 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
}
}