在 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
,例如 Button
s 将是 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
}
}