First off I am very new to WPF MVVM and a bit confused. People say that generally in MVVM the best practice is not to have any code behind. I have found that some methods are way easier to achieve in code behind than in viewmodel (e.g MouseMove
) and that led me thinking between the differences of these 2 following examples:
1) Using RelayCommand
:
View
<Button Command="{Binding AlertCommand}"></Button>
ViewModel
public RelayCommand AlertCommand { get; set; }
public void Alert()
{
MessageBox.Show("message");
}
2) calling ViewModel
methods from code behind:
View
<Button PreviewMouseLeftButtonUp="OnMouseLeftButtonUp"></Button>
View code behind
private void OnMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var ctx = (MainViewModel) this.DataContext;
ctx.Alert();
}
Is using code behind here wrong? What are my benefits of not using code behind?
The MVVM pattern is a best practice when building UWP, WPF, and Xamarin.Forms apps. The main advantage is that you are able to decouple the logic from the presentation and potentially could present a single view model by multiple different views and could switch views without having to modify the view model significantly. This is a great advantage when building cross-platform apps with native UI, which MvvmCross framework uses to a great extent for example.
Having an empty code-behind is however definitely just an ideal, which is usually not easy and not always necessary to achieve. Sometimes you need to use code-behind for purely view-related manipulation like changing layout for different window sizes, controlling animations, etc. For such actions, code-behind is a much better fit than trying to force this somehow into the VM.
Comparing your two approaches, using the RelayCommand
-based one over the direct method call is preferable, because it has less direct tie to the method itself. If you wanted, you could switch the RelayCommand
instance in the VM for a different implementation (calling different method) at runtime, and thanks to binding the button could now perform a different action. This can be used in editor-like apps where some tools may have different functionality based on current context the app is in.
Also, for controls which do not offer a Command
you can use EventTrigger
hand in hand with InvokeCommandAction
(both defined withing Expression Blend SDK) which will allow you to "convert" an event to a command call, even with your defined transformation of EventArgs
.