【发布时间】:2012-06-18 06:49:20
【问题描述】:
我想绑定到 XAML 中的 ObservableCollection 并在那里应用分组。原则上,这很好用。
<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>
然后数据绑定表达式变成ItemsSource="{Binding Source={StaticResource ResourceKey=cvs}}"而不是ItemsSource="{Binding Path=TestTemplates}"。
起初,一切看起来都很酷,直到我想从视图模型中刷新 UI。问题是,CollectionViewSource.GetDefaultView(TestTemplates) 返回的视图与应用分组的 XAML 中的视图不同。因此,我无法设置选择或对其进行任何有用的操作。
我可以通过将列表再次直接绑定到视图模型的属性并在代码隐藏中设置分组来修复它。但我对这个解决方案不太满意。
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"));
}
}
我想,原因已经是given by John Skeet here。
尽管如此,我希望应该有一种方法来获得正确的视图。我错了吗?
【问题讨论】:
-
你做错了。虚拟机不应该知道视图。如果要更新视图,请确保它绑定到的属性是 ObservableCollection 或者您的代码在修改集合时显式引发 NotifyPropertyChanged。
-
@PanagiotisKanavos:列表视图中的内容实际上是在
ObservableCollection中,并且UI 中的项目确实会在属性更改时更新。但是分组不尊重这一点。一个已知的解决方法是强制更新,即CollectionViewSource.GetDefaultView(…).Refresh。 -
在 .NET 4.5 中,这将通过 ICollectionViewLiveShaping 来解决。
标签: c# wpf xaml code-behind collectionviewsource