Programmatic WPF Bindings and Chaining CollectionViewSource

In my Pluralsight course WPF Data Binding in Depth, I barely covered using bindings from code behind, mainly because where bindings really shine is in XAML. But there are occasions where you need to set a binding from code behind. I got a question on my course discussion about an example I showed where I show how to chain CollectionViewSources (CVSs) to get a Master-Details presentation of parent and child collections and how you could do that from code behind. So rather than answer there, I’ll do it here where it is a little easier to show code and explanation.

First off, to chain the CVSs, you set them up as Resources like so:

<Window.Resources>

<CollectionViewSourcex:Key="customerViewSource"/>

<CollectionViewSourcex:Key="customerOrdersViewSource"

Source="{Binding Orders, Source={StaticResource customerViewSource}}"/>

<CollectionViewSourcex:Key="customerOrdersOrderItemsViewSource"

Source="{Binding OrderItems, Source={StaticResource customerOrdersViewSource}}"/>

Window.Resources>

In my course, I show how you can get all this done through simple drag and drop using the Data Sources Window. Here I will just focus on the code.

In this case, I am chaining two levels deep, from a Customers collection, to the Orders for each Customer, to the OrderItems for each Order. You can see that the key is to set the Source property of the child CVS to the parent CVS through a binding.

Then naturally there are UI elements, typically DataGrids, whose ItemsSource property gets bound to each CVS to present that level in the hierarchy:

<DataGridx:Name="ordersDataGrid"

ItemsSource="{Binding Source={StaticResource customerOrdersViewSource}}" ...>



So how would you do this from code behind? First you need to create the CVS instances:

private CollectionViewSource _customerViewSource = new CollectionViewSource();

private CollectionViewSource _customerOrdersViewSource

= new CollectionViewSource();

private CollectionViewSource _customerOrdersOrderItemsViewSource

= new CollectionViewSource();



Then you need to create the bindings for the child (and grandchild) CVS in code in the constructor or Loaded event:

var ordersBinding = new Binding("Orders");

ordersBinding.Source = _customerViewSource;

BindingOperations.SetBinding(_customerOrdersViewSource,

CollectionViewSource.SourceProperty, ordersBinding);



var orderItemsBinding = new Binding("OrderItems");

orderItemsBinding.Source = _customerOrdersViewSource;

BindingOperations.SetBinding(_customerOrdersOrderItemsViewSource,

CollectionViewSource.SourceProperty, orderItemsBinding);



FrameworkElement derived types have their own SetBinding method on them. For normal DependencyObjects like a CVS, you use the BindingOperations class to set a binding programmatically, passing it the object you want to set the binding on, the dependency property that will be the target on that object, and the binding you want to set it to.

Finally, since the XAML won’t have access to those CVSs (unless you expose them through a property you can bind to), you can set the bindings for the DataGrids in the code behind as well.

ordersDataGrid.SetBinding(DataGrid.ItemsSourceProperty,

new Binding { Source = _customerOrdersViewSource });

orderItemsDataGrid.SetBinding(DataGrid.ItemsSourceProperty,

new Binding { Source = _customerOrdersOrderItemsViewSource });

Then you need to set the root collection on the root CVS Source property (after loading the data from somewhere naturally).

_customerViewSource.Source = Customers;

Then you are off and running.

Again, I rarely set bindings programmatically like this. Most of the time it is better to keep your bindings in the XAML. But if you need to, there you go.

You can download a full sample here.