I wanted to bind to an ObservableCollection
in XAML and also apply the grouping there. In principle, this worked fine.
<UserControl.Resources>
<CollectionViewSource x:Key="cvs" Source="{Binding Path=TestTemplates}">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Title"/>
</CollectionViewSource.SortDescriptions>
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="TestCategory"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</UserControl.Resources>
Then the data binding expression became ItemsSource="{Binding Source={StaticResource ResourceKey=cvs}}"
instead of ItemsSource="{Binding Path=TestTemplates}"
.
At first, everything seemed cool, until I wanted to refresh the UI from the view model. The problem is, that CollectionViewSource.GetDefaultView(TestTemplates)
returned a different view than the one from XAML where the grouping was applied. Thus, I could not set selection or do anything useful with it.
I could fix it by binding the list again directly to the view model's property and setting up the grouping in the code-behind. But I'm not that happy with this solution.
private void UserControlLoaded(object sender, RoutedEventArgs e)
{
IEnumerable source = TemplateList.ItemsSource;
var cvs = (CollectionView)CollectionViewSource.GetDefaultView(source);
if (cvs != null)
{
cvs.SortDescriptions.Add(new SortDescription("Title", ListSortDirection.Ascending));
cvs.GroupDescriptions.Add(new PropertyGroupDescription("TestCategory"));
}
}
I assume, the reason for that is already given by John Skeet here.
Nevertheless, I would expect that there should be a way to get the right view. Am I wrong?
ObservableCollection
and the items in the UI do update on a property change. But the grouping does not respect that. A known workaround is to force the update, i.e.CollectionViewSource.GetDefaultView(…).Refresh
. – Carltoncarly