Problem grouping data using CollectionViewSource

When I try to group data using CollectionViewSource I get an error. Am I missing something or is this a bug

BindingExpression path error: 'Groups' property not found on 'object' ''null''.

'BindingExpression':Path='Groups'; DataItem=''null'';

target element is ''TreeView' (Name='')'; target property is 'ItemsSource' (type 'IEnumerable');

Cannot find mentor for target element.

'BindingExpression':Path='DisplayCollection'; DataItem=''null'';

target element is ''CollectionViewSource' (hashcode='50510248')'; target property is 'Source' (type 'Object');

<Window x:Class="Test.Window1"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

Title="Test" Height="300" Width="300"

Name="wind"

>

<Window.Resources>

<CollectionViewSource x:Key="cvs" Source="{Binding DisplayCollection, ElementName=wind, Mode=OneWay}">

<CollectionViewSource.GroupDescriptions>

<PropertyGroupDescription PropertyName="Key"/>

</CollectionViewSource.GroupDescriptions>

</CollectionViewSource>

<HierarchicalDataTemplate x:Key="categoryTemplate" ItemsSource="{Binding Path=Items}" ItemTemplate="{StaticResource itemTemplate}">

<TextBlock Text="{Binding Path=Name}" FontWeight="Bold"/>

</HierarchicalDataTemplate>

<DataTemplate x:Key="itemTemplate">

<TextBlock Text="{Binding Path=Value}"/>

</DataTemplate>

</Window.Resources>

<Grid>

<TreeView ItemsSource="{Binding Source={StaticResource cvs}, Path=Groups}" Width="150" ItemTemplate="{Binding Source={StaticResource categoryTemplate}}">

</TreeView>

</Grid>

</Window>

public partial class Window1 : Window

{

private ObservableCollection<KeyValuePair<string, string>> displayCollection;

public ObservableCollection<KeyValuePair<string, string>> DisplayCollection

{

get { return this.displayCollection; }

}

public Window1()

{

InitializeComponent();

this.displayCollection = new ObservableCollection<KeyValuePair<string, string>>();

this.displayCollection.Add(new KeyValuePair<string,string>("S","s1"));

this.displayCollection.Add(new KeyValuePair<string, string>("S", "s2"));

this.displayCollection.Add(new KeyValuePair<string, string>("B", "b1"));

this.displayCollection.Add(new KeyValuePair<string, string>("B", "b2"));

}

}



Answer this question

Problem grouping data using CollectionViewSource

  • CodeMonkeyDave

    Hello,

    This is a really old post, but perhaps you get notified by email when a new reply comes..

    I'm hitting this exact same problem. I want to modify your GroupingTreeView sample to bind to a property of the window's DataContext.

    The property is an ObservableCollection. So instead of this:

    <CollectionViewSource x:Key="cvs" Source="{Binding Source={StaticResource animals}, Path=AnimalList}">

    <CollectionViewSource.GroupDescriptions>

    <PropertyGroupDescription PropertyName="Category"/>

    </CollectionViewSource.GroupDescriptions>

    </CollectionViewSource>

    I want to replace the first line with something like this:

    <CollectionViewSource x:Key="cvs" Source="{Binding Path=AnimalList}">

    Is this possible these days Thank you very much if you do get this!

    Sam


  • Gekon

    Hi Cezary,

    In Feb CTP anything inside the resources section does not have a "parent" or "mentor", like elements in the logic and visual tree do. This causes your binding to fail because the CollectionViewSource does not inherit the DataContext property set in the Window. My opinion is that the "mentor" of a resource should be the element that contains that resource (in this case the Window), and thankfully the people that own this feature in Avalon are of this opinion too. I'm glad to see we are getting customer feedback in this direction :) If the "mentor" of your CollectionViewSource in the resources is the Window, the CVS will inherit whatever DataContext you set in the Window and the markup in your previous post just works. So it is very likely that this scenario will work the way you want it to in a future release of Avalon :)

    Bea



  • VisualHint

    Well I haven't read all your code to carefully, but I could already see an obvious problem.

    You are binding with a normal property (as opposed to a dependency property) which is initialized after InitializeComponent().

    Hence it will always be null from the perspective of the data binding!


  • Nichole158860

    Hi Cezary,

    The CollectionViewSource in your sample is trying to group a null collection because your binding to the collection is failing:

    <CollectionViewSource x:Key="cvs" Source="{Binding DisplayCollection, ElementName=wind, Mode=OneWay}">

    The second part of the debug message you saw says that the data item for the binding with Path=DisplayCollection and target CollectionViewSource's Source is null, which means that the binding could not find a source. The reason for this is that the scope of an ElementName binding in the resources does not include the Window that contains those resources. If you want more technical details on this, I can ask an Element Services expert to chime in.

    One way to get around this issue is to build your collection as a separate class and instantiating it by adding it to the resources directly:

    public class MySource
    {
    private ObservableCollection<KeyValuePair<string, string>> displayCollection;

    public ObservableCollection<KeyValuePair<string, string>> DisplayCollection
    {
    get { return this.displayCollection; }
    }

    public MySource()
    {
    this.displayCollection = new ObservableCollection<KeyValuePair<string, string>>();
    this.displayCollection.Add(new KeyValuePair<string, string>("S", "s1"));
    this.displayCollection.Add(new KeyValuePair<string, string>("S", "s2"));
    this.displayCollection.Add(new KeyValuePair<string, string>("B", "b1"));
    this.displayCollection.Add(new KeyValuePair<string, string>("B", "b2"));
    }
    }

    <Window.Resources>
    <local:MySource x:Key="src" />

    <CollectionViewSource x:Key="cvs" Source="{Binding Source={StaticResource src}, Path=DisplayCollection}">
    <CollectionViewSource.GroupDescriptions>
    <PropertyGroupDescription PropertyName="Key"/>
    </CollectionViewSource.GroupDescriptions>
    </CollectionViewSource>
    (...)
    </Window.Resources>

    You can find here a working sample with this code: http://www.beacosta.com/Forum/GroupingCollectionViewSource.zip.

    Let me know if this works for you.



  • Jim Hughes

    That works but I need to bind to a collection that already exists. If I assign that collection to the dataContext of a window and then bind it directly to TreeView the binding works... but when I go through CollectionViewSource it fails... The only difference is that one binding happens in the Resources section the other one does not...

    Am I missing something Is resource section treated differently

    <Window x:Class="Test.Window1"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:l="clr-namespace:Test"

    Title="Test" Height="300" Width="300"

    Name="wind"

    >

    <Window.Resources>

    <CollectionViewSource x:Key="cvs" Source="{Binding}"> <------- THIS DOES NOT WORK

    <CollectionViewSource.GroupDescriptions>

    <PropertyGroupDescription PropertyName="Key"/>

    </CollectionViewSource.GroupDescriptions>

    </CollectionViewSource>

    <HierarchicalDataTemplate x:Key="categoryTemplate" ItemsSource="{Binding Path=Items}" ItemTemplate="{StaticResource itemTemplate}">

    <TextBlock Text="{Binding Path=Name}" FontWeight="Bold"/>

    </HierarchicalDataTemplate>

    <DataTemplate x:Key="itemTemplate">

    <TextBlock Text="{Binding Value}"/>

    </DataTemplate>

    </Window.Resources>

    <Grid>

    <TreeView ItemsSource="{Binding Source={StaticResource cvs}, Path=Groups}" Width="150" ItemTemplate="{Binding Source={StaticResource categoryTemplate}}">

    </TreeView>

    <TreeView ItemsSource="{Binding}" Width="150"> <------- THIS WORKS

    </TreeView>

    </Grid>

    </Window>

    public partial class Window1 : Window

    {

    public Window1()

    {

    InitializeComponent();

    ObservableCollection<KeyValuePair<string, string>> displayCollection =

    new ObservableCollection<KeyValuePair<string, string>>();

    displayCollection.Add(new KeyValuePair<string,string>("S","s1"));

    displayCollection.Add(new KeyValuePair<string, string>("S", "s2"));

    displayCollection.Add(new KeyValuePair<string, string>("B", "b1"));

    displayCollection.Add(new KeyValuePair<string, string>("B", "b2"));

    this.DataContext = displayCollection;

    }

    }


  • Thiru_

    Ed,

    We appreciate the feedback. As I mentioned in my previous post, I completely agree with you guys. We have discussed this issue extensively, and the feedback we get from customers weights a lot in our decisions. Hopefully you will see this working in a future release of Avalon (although unfortunately we didn't discuss this on time for Beta 2).

    Bea



  • mlopez

    I second this motion -- I had the same difficulty.
  • Problem grouping data using CollectionViewSource