Often I hear the discussion where to put certain code within the MVVM pattern in WPF to achieve loose coupling and reduce unnecessary dependencies. Frameworks like PRISM (or Composite Application Guidance for WPF), Caliburn, CoreMVVM and others try to address this problem in different ways. From speakers at conferences you may hear things like: “Never put any code in the code-behind file, except InitializeComponent.” Others make excessive use of code behind and leave the view model relatively dumb.
According to my experiences and beliefs you should always find the right balance of where to put what kind of code. For myself, I try to follow the undermentioned guidelines:
- The View which consists of the XAML file and code-behind should never have a reference to its ViewModel. It should not even know the type of the view model (see my last blog entry on how to achieve this). Having said that it is evident that the ViewModel should not know the View it is bound to.
- Communication between View and ViewModel takes place only by the use of Binding. Use Two-Way Binding if needed. Maybe use helper properties in the ViewModel. Implement INotifyPropertyChanged and use classes like ObservableCollection to notify the View of changes.
- Code-Behind files may contain additional code if that code represents intrinsic functionality that can not or not easily be achieved by using Binding. An example might be the automatic update of a field according to another field in the View based upon a more complex calculation. You may also use Converters.
- Use Commands to route events from the View to the ViewModel. Josh Smith made a really cool and lightweight CommandSink solution which uses RoutedCommands. The disadvantage in Josh’s example is that you need a type reference to your ViewModel in the View. But there are other solutions to avoid that (for those who are interested, you may download the BASTA 2010 example project from Tobias Richling).
In order to meet all of these guidelines you will need quiet some infrastructure in your application that produces some kind of overhead and may even have an impact on performance. So it is up to you to decide if’s worth to have that overhead.