Behaviors and all that fun stuff…
The other day I was catching up on some of Dan Wahlin’s posts and I read his post about providing a DataContext to controls that needed to access the ViewModel but were in a sub-collection. He went through some good approaches as to how one could go about solving this problem.
I would like to also offer up another approach that is quite similar to his but with a twist. I agree that, if possible, it keeps things simple if you can provide a way to reach out to the underlying ViewModel no matter what the nesting level your control resides in. In my experience, I rarely find a solution that works best for all of my scenarios but I have found several solutions that tend to handle most of the the issues I come across.
Before we go further, I would like to present the general approach that I use to build these solutions. I use Behaviors. These guys live in the System.Windows.Interactivity namespace. They provide a very powerful way to write code once and use over and over in your Xaml.
I will present them first in a list and then provide a detailed explanation when each would be used:
- DataContextToDomainDataSourceBehavior — this behavior exposes a property, “ControlName”. It uses this to walk up the Visual Tree until it finds such a control and then sets the DataContext of the underlying control for which this behavior is set. The DataContext gets set on the Loaded event.
- ItemSourceBehavior — This behavior has a lot of flexibility. It exposes “ItemsSourceName”, “IsEnum”, “EnumFilter” properties. This behavior works on any ItemsControl, DataGrid, and Telerik RadGridView. If the IsEnum flag is set, then it is smart enough to set the ItemsSource to the named enum. Otherwise, it will find the named property on the DataContext. This behavior explicitly looks for the first UserControl it can find and grabs its DataContext.
- ItemSourceBindingBehavior — This is basically the same as the previous behavior but this one binds the ItemsSource to the underlying property. This facilitates for a more MVVM style of programming.
- ItemSourceToDomainDataSourceBehavior — This fires on the loaded event and has a property that holds the name of a DomainDataSource. This behviour explicitly looks for the first UserControl it can find and then looks for a DomainDataSource with the given name. If it finds it then ItemSource property is bound to the DomainDataSource. This happens for ItemsControls and the DataGrid.
Each of these behaviors performs a specific task and has certain capabilities. As you can see, there may be scenarios that you could use that are not exposed by what I have show here. I will go further into how these work in a later post.