Posts Tagged ‘CollectionContainer’

CompositeCollection Binding Problem – It’s not part of the Visual Tree

May 31, 2011 6 comments

XAML is fantastic, but occasionally unpredictable which can cause some confusion.

One instance of this is the CompositeCollection tag which is used to build up a collection of values from a number of sources.

An example of this might be as simple as adding a “Please choose…” to the top of a drop down list or more complex scenarios, such as building up a list of products from different suppliers. In most cases, when using MVVM these kind of situations can be handled in the View Model, but even so, it can still be useful to build up lists in the XAML.

One such example I hit recently was creating a context menu for filtering on a data grid. I wanted to filter based on the values in the column, but also add two sorting options at the top of the list. A simplified version of the XAML is shown in Listing 1 below.

        <MenuItem Header="Sort Ascending" />
        <MenuItem Header="Sort Descending" />
        <Separator />
        <CollectionContainer Collection="{Binding Path=FilterOptions}}" />

Listing 1 – Simplified code to show an example usage of CompositeCollection

However if you try to use code such as this you’ll very quickly hit the following binding problem.

Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=FilterOptions; DataItem=null; target element is ‘CollectionContainer’ (HashCode=23627591); target property is ‘Collection’ (type ‘IEnumerable’)

Why? Well it is all down to the fact that the data context of the XAML, specified at the top level that is inherited down through the elements actually goes down the Visual Tree. The killer is that the CompositeCollection, having no visual properties, is not part of the visual tree and therefore does not inherit the data context. The CompositeCollection has no clue what “FilterOptions” is in this example and thus throws a binding error.

Luckily we can easily solve this as all elements have access to the static resources of the XAML so we can easily create a bridging static resource that does the binding that we need and then use that within the composite collection. Listing 2 shows the static resource that we need in this instance.

    <CollectionViewSource x:Key="FilterOptionsBridge" Source="{Binding Path=Filters}" />

Listing 2 – Static resource bridging back to the data context

And finally we can adjust our CollectionContainer to point to the static resource, as in Listing 3.

<CollectionContainer Collection="{Binding Source={StaticResource FilterOptionsBridge}}" />

Listing 3 – Update to reference the static resource

As a side note, the CollectionViewSource tag needs to bind to an IEnumerable, so if you are binding to a CollectionView or one of the derived classes you’ll need to change the binding to be to the SourceCollection property as shown in Listing 4.

    <CollectionViewSource x:Key="FilterOptionsBridge" Source="{Binding Path=Filters.SourceCollection}" />

Listing 4 – Updated binding to reference the SourceCollection