You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何重复初始化后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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 06:32:38