Search code examples
c#wpfwpf-controlscollectionviewsource

WPF - Using CollectionViewSource with ALREADY grouped data


I have a ViewModel that is used in Windows 8, Android and iOS as part of a Xamarin Project. I now need to display that VM in a ListView in WPF.

That VM exposes some already grouped data as ObservableCollection<GroupedResult<string, SearchResult>>. GroupResult has a Key (String) property and an IEnumerable Source property

With a Windows 8 ListView I can assign that data to a CollectionViewSource (CVS), tell the CVS the path to the Items property PropertyPath("Source") and it works fine.

However WPF seems to want an ungrouped List fed to its CVS so it can Group it all itself. How do I tell the WPF CVS that the VM contains already Grouped data?


Solution

  • I am afraid that the System.Windows.Data.CollectionViewSource class in WPF has no IsSourceGrouped or equivalent property so you cannot really tell it that the data is already grouped.

    You basically have two options.

    1. Ungroup the source collection and set the Source property of the CollectionViewSource to the ungrouped collection and add a PropertyGroupDescription to its GroupDescriptions collection as usual: https://msdn.microsoft.com/en-us/library/ms742542(v=vs.110).aspx

    2. Set the Source to the grouped collection and define an ItemTemplate for the Grouping objects:

      public MainWindow()
      {
          InitializeComponent();
          List<User> items = new List<User>();
          items.Add(new User() { Name = "John Doe", Age = 42, Sex = SexType.Male });
          items.Add(new User() { Name = "Jane Doe", Age = 39, Sex = SexType.Female });
          items.Add(new User() { Name = "Sammy Doe", Age = 13, Sex = SexType.Male });
      
          var result =
              from x in items
              group x by x.Sex into g
              orderby g.Key
              select g;
      
          listBox.ItemsSource = result;
      }
      

       <ListBox x:Name="listBox">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Expander Header="{Binding Key}">
                        <ListBox ItemsSource="{Binding}">
                            <ListBox.ItemTemplate>
                                <DataTemplate>
                                    <StackPanel>
                                        <TextBlock Text="{Binding Name}"/>
                                    </StackPanel>
                                </DataTemplate>
                            </ListBox.ItemTemplate>
                        </ListBox>
                    </Expander>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>