Commands are used for handling Events in WPF while respecting the MVVM-Pattern.
A normal EventHandler would look like this (located in Code-Behind):
public MainWindow()
{
_dataGrid.CollectionChanged += DataGrid_CollectionChanged;
}
private void DataGrid_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
//Do what ever
}
No to do the same in MVVM we use Commands:
<Button Command="{Binding Path=CmdStartExecution}" Content="Start" />
I recommend to use some kind of prefix (
Cmd) for your command properties, because you will mainly need them in xaml - that way they are easier to recognize.
Since it's MVVM you want to handle that Command (For Button "eq" Button_Click) in your ViewModel.
For that we basically need two things:
A simple example could look like this:
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.
}
So what is this doing in detail:
The ICommand is what the Control in xaml is binding to. The RelayCommand will route your command to an Action (i.e call a Method). The Null-Check just ensures that each Command will only get initialized once (due to performance issues). If you've read the link for the RelayCommand above you may have noticed that RelayCommand has two overloads for it's constructor. (Action<object> execute) and (Action<object> execute, Predicate<object> canExecute).
That means you can (aditionally) add a second Method returning a bool to tell that Control wheather the "Event" can fire or not.
A good thing for that is that Buttons for example will be Enabled="false" if the Method will return false
CommandParameters
<DataGrid x:Name="TicketsDataGrid">
<DataGrid.InputBindings>
<MouseBinding Gesture="LeftDoubleClick"
Command="{Binding CmdTicketClick}"
CommandParameter="{Binding ElementName=TicketsDataGrid,
Path=SelectedItem}" />
</DataGrid.InputBindings>
<DataGrid />
In this example I want to pass the DataGrid.SelectedItem to the Click_Command in my ViewModel.
Your Method should look like this while the ICommand implementation itself stays as above.
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
}
}