Sorting a CollectionView's Groups on a property generated by IValueConverter
I am using CollectionViewSource's groupings to display a virtual "aggregate" view of a collection of details; basically the sample seen here: ListBox Grouping, Sorting, Subtotals and Collapsible Regions
To summarize the relevant part of the example, your groupings can expose an aggregated property from their details via a ValueConverter, like so:
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.Conta开发者_StackOverflowinerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type GroupItem}">
<Grid>
<!--[..Snip..]-->
<TextBlock Grid.Column="4"
Text="{Binding StringFormat=\{0:C\},
Converter={StaticResource groupItemSalesSubtotalConverter}}"
TextAlignment="Right" />
<!--[..Snip..]-->
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListBox.GroupStyle>
Note that the TextBlock above is bound directly to the GroupItem's binding, so the converter receives the entire CollectionViewGroup
and its children and can drill down into the details to sum the subtotal of the items in the group.
The problem is, since this value isn't itself a property, is it possible to sort the groups by their Subtotal?
This obviously can't be handled by SortDescription
. I've seen suggestions that ListCollectionView's CustomSort
property, which takes an IComparer
implementation can be used in a situation like this, but I don't see how: The Compare()
method receives pairs of detail items regardless of their grouping, I can't determine the subtotals at that point.
Is there any way I can sort these groups without needing to make them entities in their own right (i.e. have a CollectionView at the summary level and another CollectionView at the detail level)?
I believe the order of the groups shown in the ItemsControl is determined by the collection's items sort order.
So, normally, you would sort first by the grouping property, and then second by the order you want to achieve within the group...
In your case you want to sort the groups by another property (i.e. the sum if the items in that group). The only way I know to do this easily is to add a new property to the item, which returns the sum of each group (or an arbitrary sort key, based on the required order). You can then sort the collection by that property, which will give you the required group ordering.
This doesn't seem terribly efficient or elegant, because you need to set/calculate the sum of the group for each item in the collection, in effect calculating the grouping in code. However, I don't know of a better way.
精彩评论