One of the biggest pain points of MVVM is the boilerplate code that is necessary for it to function. The code I’m referring to is the code needed to Hook and Unhook, initialize/shutdown, load/unload the things the ViewModel needs to do before and after being used by the View. Because the ViewModel is usually forced to hook events coming from the Model to know when to emit its own set of events to update the View, it means knowing the lifetime of the View is critical to knowing when to unhook those events from the Model.
An idea I came up with while working on our level editor a few months back was this thought that, what if I could use the attached behavior pattern to actually solve the problems of ViewModels’s boilerplate code for hooking and unhooking those event on the model handlers.
First you’ll need a base class for your ViewModel, I actually went with an interface instead because I felt it was better suited for this role. The ViewModel I decided to go with is extremely basic, there’s just a Load and Unload method and we also use the interface INotifyPropertyChanged. In our own code I also defined a ViewModel class that derives from this interface that I tended to use most of the time, that just stubs out these methods with your basic implementations just so I didn’t need to implement a RaisePropertyChanged method 40 times.
Next we need to create an attachable property that has logic associated with it that reacts to changes in the control, the community has come to call these attachable behaviors.
The job of this attachable behavior will be to notify our IViewModel that is databound to the control, when the control is loaded and when the control is unloaded. That way we can just put all our event hooking and handling code into our ViewModel, and never need to worry about manually unhooking those events elsewhere ever again.
Whenever the DataContext on the View is changed, we want to Unload() the old ViewModel that was attached and Load() the new one. Also, whenever the control is Loaded or Unloaded, do the same for the ViewModel.
There are some additional things that need to be taken into account when dealing with IsAsync=True DataContext’s. Additionally there’s a bit of code to handle the problem with some WPF controls that actually sometimes send multiple Loaded events.
The way you would use this is to place the property on the controls that are the primary targets when you’re data binding your ViewModel to your view on. For example, suppose I had a ListBox with a series of ListBoxItems, there was a ViewModel databound as the ItemsSource of the ListBox (which will also set the DataContext of the ListBox to the ItemsSource). Also imagine that there is a ViewModel for each item in the list. You would place the following property on the ListBox declaration in XAML. You would also place this property on the first control element of whatever DataTemplate you defined for the ViewModel representing each element in the list.
You can download the full source files for both of these classes here, there is more documentation for these classes in those files that I didn’t want to include in the post.