Where to put events when using MVVM?
Kyle is correct in that your handlers should appear in the view model. If a command property doesn't exist then you can use an interaction trigger instead:
<DataGrid>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding Mode=OneWay, Path=OpenClientCommand}" CommandParameter="{Binding ElementName=searchResults, Path=SelectedItems}" />
</i:EventTrigger>
</i:Interaction.Triggers>
... other stuff goes here ...
</DataGrid>
Or you can use MVVM Lite's EventToCommand, which also allows you to pass in the message parameters:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<cmd:EventToCommand Command="{Binding ClosingCommand}" PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
Which is used in in this case to cancel the window close event in response to the "Are you sure you want to quit?" dialog:
public ICommand ClosingCommand { get { return new RelayCommand<CancelEventArgs>(OnClosing); } }
private void OnClosing(CancelEventArgs args)
{
if (UserCancelsClose())
args.Cancel = true;
}
Relevant namespaces are as follows:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd ="http://www.galasoft.ch/mvvmlight"
No you should not put events in code behind. In MVVM (Model-View-ViewModel) design pattern, the view model is the component that is responsible for handling the application's presentation logic and state. This means that your view's code-behind file should contain no code to handle events that are raised from any user interface (UI) element.
for eg if you have button in your xaml
<Button Content="OK" Click="btn_Click"/>
protected void btn_Click(object sender, RoutedEventArgs e)
{
/* This is not MVVM! */
}
Instead you can use WPF Command.All you have to do is bind to its Execute and CanExecute delegates and invoke your command.
So your code will now be
public class ViewModel
{
private readonly DelegateCommand<string> _clickCommand;
public ViewModel()
{
_clickCommand = new DelegateCommand(
(s) => { /* perform some action */ }, //Execute
null
} //CanExecute );
public DelegateCommand ButtonClickCommand
{
get { return _clickCommand; }
}
}
<Button Content="COOL" Command="ButtonClickCommand"/>