13
votes

'ContentTemplate' is a DataTemplate that displays an object which has a member 'FooList' (an ObservableCollection).

<DataTemplate x:Key="ContentTemplate">
    <ListBox ItemsSource="{Binding Path=FOO}">
        ...
    </ListBox>
</DataTemplate>

I need to be able to filter that FooList using a CollectionViewSource. This is usually been straight forward but I can't seem to get the binding to work within a DataTemplate. I attempted to this:

<DataTemplate x:Key="ContentTemplate">
    <DataTemplate.Resources>
        <CollectionViewSource x:Key="CVS" Source="{Binding Path=FooList}" Filter="FooFilter"/>
    <DataTemplate.Resources>
    <ListBox ItemsSource="{Binding Source={StaticResource CVS}}">

The errors I get from this is:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=FooList; DataItem=null; target element is 'CollectionViewSource' (HashCode=52991666); target property is 'Source' (type 'Object')

Which sounds to me like it's looking for 'FooList' on the CollectionViewSource instead of the object bound to the DataTemplate.

So... how do I get this to look at the correct object?

3
I'm having the same problem. Only thing I can think of is that the CVS doesn't know the correct source for the binding (your 'FooList' member) which should be the DataContext at this level. Is there a way to explicitly set the source on the CVS to the current DataContext of the DataTemplate? Again, should be assumed but this isn't working for us both. (The only difference between yours and mine is that you're binding to an internal ListBox. I'm binding to the child items of a HierarchicalDataTemplate for use in a treeview. But other than that, you and I are in the same boat.Mark A. Donohoe
It seems to me that it's not supposed to have access to the Data of the DataTemplate inside the resource part. Does anyone know if that is correct?Ingó Vals

3 Answers

29
votes

As I understand it, the DataTemplate acts as instructions on what to insert into the visual tree but does not become a part of the visual tree itself. I only came to this hypothesis after running into the same problem you've described above. I fixed the issue by attaching the CollectionViewSource to the resources of an element that would be part of the visual tree, in my case a grid. Here is the sample that did work:

<DataTemplate DataType="{x:Type TypedLists:AssetModelListViewModel}">
    <Grid>
        <Grid.Resources>
            <CollectionViewSource x:Key="items"
                                  Source="{Binding}">
                <CollectionViewSource.SortDescriptions>
                    <scm:SortDescription PropertyName="AssetType.AssetCategory.Name" />
                    <scm:SortDescription PropertyName="AssetType.Name" />
                    <scm:SortDescription PropertyName="Manufacturer.Name" />
                </CollectionViewSource.SortDescriptions>
            </CollectionViewSource>
        </Grid.Resources>

        <ListView ItemsSource="{Binding Source={StaticResource items}}">

        </ListView>
    </Grid>
</DataTemplate>
0
votes

I worked around this issue by moving the data template into a user control.

-1
votes

I think you need to bind to the view of the CollectionViewSource:

<ListBox ItemsSource="{Binding Path=View, Source={StaticResource CVS}}">