Question

I'm a fairly novice programmer, and making a Windows Store App. I have an object that contains an ObservableCollection(Of T) that I want to group for display in a ListView. Using LINQ to return a set of grouped items seems like it would be the best and easiest choice. Every piece of documentation I could find says that Group By returns IEnumerable(Of IGrouping(Of TKey, TItem)) and you set CollectionViewSource.IsSourceGrouped to True, bind to the CVS and it should all work perfectly. Right?

Not so much.

I have a class that contains

Public Property Items As ObservableCollection(Of Item)

Public ReadOnly Property GroupedItems As IEnumerable
    Get
        ' Return grouped items
    End Get
End Property

And in the XAML for the page, where GroupedItems is set as the Page's DataContext in code-behind:

<Page.Resources>
    <CollectionViewSource x:Name="GroupedItems" Source="{Binding}" IsSourceGrouped="True" />
</Page.Resources>

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
    <ListView ItemsSource="{Binding Source={StaticResource GroupedItems}}">
        <ListView.GroupStyle>
            <GroupStyle.HeaderTemplate>
                <DataTemplate>
                    <!-- Template -->
                </DataTemplate>
            </GroupStyle.HeaderTemplate>
        </ListView.GroupStyle>
        <ListView.ItemTemplate>
            <DataTemplate>
                <!-- Template -->
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

Now, if I bind the ListView to the ObservableCollection(Of Item) directly, the ListView renders all the items as expected, following the ItemTemplate. But when it is bound to the supposedly-grouped CollectionViewSource, the ListView renders the groups according to the HeaderTemplate, but it doesn't render any of the items within the group.

I've inspected the results of the LINQ logic:

Dim x = From i As Item In Items
        Group i By Key = i.SubItem Into Group

And x has a Key property and a Group property, though it is some kind of IEnumerable(Of anonymous) type rather than an IEnumerable(Of IGrouping(Of TKey, TItem)).

So what am I doing wrong here? Is there another caveat to the VB.NET implementation of LINQ that I'm missing? Is there a property I'm forgetting to set? What is the right way to do this?

Was it helpful?

Solution

I found a solution, though I don't know that it is the ideal solution. Because the result of the LINQ query places the items in the Group property of its anonymous type, CollectionViewSource needs to know that. So by adding ItemsPath="Group" to the XAML defining the CollectionViewSource, it now displays both the group headers and the containing items.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top