为何重复初始化后WPF DataGrid自动排序功能失效?
WPF DataGrid 重复初始化后实时排序失效及无IsLiveFiltering仍过滤生效的原因
问题场景
我有一个用于测试的UserControl,XAML代码如下:
<Grid> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <DataGrid x:Name="TestGrid" AutoGenerateColumns="False"> <DataGrid.Columns> <DataGridTextColumn Header="Id" Binding="{Binding Path=Id}"/> <DataGridTextColumn Header="Name" Binding="{Binding Path=Name}"/> </DataGrid.Columns> </DataGrid> <StackPanel Grid.Row="1" Orientation="Horizontal"> <Button Content="Init View" Click="InitViewButton_Click"/> <Button Content="Add" Click="AddButton_Click"/> <Button Content="Change Ids" Click="ChangeIdButton_Click"/> <Button Content="Filter X" Click="FilterButton_Click"/> </StackPanel> </Grid>
对应的后台代码:
public ListCollectionView TestView {get; set;} public ObservableCollection<TestItem> TestItems {get; set;} private void init() { var result = new ObservableCollection<TestItem>() { new TestItem() { Id = 1, Name = "First A" }, new TestItem() { Id = 2, Name = "Second A" }, new TestItem() { Id = 3, Name = "Third A" }, }; TestItems = result; var view = new ListCollectionView(TestItems); view.SortDescriptions.Add(new SortDescription(nameof(TestItem.Id), ListSortDirection.Descending)); view.IsLiveSorting = true; view.Filter = o => (o as TestItem)?.Name.Contains("A") ?? false; TestView = view; } private void InitViewButton_Click(object sender, RoutedEventArgs e) { init(); TestGrid.ItemsSource = TestView; TestGrid.Items.Refresh(); } private void AddButton_Click(object sender, RoutedEventArgs e) { var item = new TestItem() { Id = 99, Name = "New AX" }; TestItems.Add(item); } private void ChangeIdButton_Click(object sender, RoutedEventArgs e) { foreach (var testItem in TestItems) { testItem.Id = Random.Shared.Next(1000); } } private void FilterButton_Click(object sender, RoutedEventArgs e) { TestView.Filter = o => (o as TestItem)?.Name.Contains("X") ?? false; }
现象描述
- 首次点击“Init View”按钮后,DataGrid正常加载数据,修改Id时行可自动重新排序,其他按钮功能正常。
- 再次点击“Init View”后,修改Id时行不再自动排序,但数据显示能正确更新;
- 未设置
IsLiveFiltering,但点击“Filter X”按钮后过滤功能仍可正常工作。
原因分析
1. 重复点击Init View后实时排序失效的原因
- TestItem未实现INotifyPropertyChanged接口:
ListCollectionView的IsLiveSorting功能需要感知源对象的属性变化,这依赖于对象实现INotifyPropertyChanged并在属性变更时触发PropertyChanged事件。你的代码中TestItem没有实现该接口,因此修改Id属性时,视图无法感知到变化,自然不会触发实时排序。 - 首次点击的“假实时排序”:首次初始化时,你调用了
TestGrid.Items.Refresh(),这会强制DataGrid重新加载视图并执行一次排序,让你误以为是实时排序生效。而第二次点击后,修改Id时没有触发任何刷新操作,因此排序不会自动更新,但DataGrid的单元格绑定会因WPF的默认行为(如焦点变更)显示最新的Id值。
2. 未设置IsLiveFiltering但过滤功能正常的原因
ListCollectionView的过滤逻辑分为两种场景:
- 实时过滤:需要开启
IsLiveFiltering并配置LiveFilteringProperties,用于自动监听属性变化并重新过滤; - 手动触发过滤:当你重新赋值
Filter委托时(比如点击“Filter X”按钮时),ListCollectionView会立即执行一次过滤逻辑,这是视图的默认行为,不需要依赖实时过滤配置。你代码中的过滤操作都是通过重新设置Filter委托触发的,因此即使没开IsLiveFiltering也能正常工作。
内容的提问来源于stack exchange,提问作者mike
相关产品推荐
相关产品推荐

