为什么在.net 4.6中更改WPF DataGrid ItemsSource如此之慢?

本文关键字:DataGrid WPF ItemsSource 如此之 net 为什么 | 更新日期: 2023-09-27 18:13:57

例如,试试下面这个简单的WPF窗口:

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <TextBox Grid.Row="0" Text="{Binding Path=Filter, UpdateSourceTrigger=PropertyChanged}" />
        <DataGrid Grid.Row="1" ItemsSource="{Binding FilteredList}">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding}" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

后面有以下代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
public partial class MainWindow : Window, INotifyPropertyChanged
{
    List<string> items = new List<string>();
    string filter = string.Empty;
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        for (int i = 0; i < 100; i++) items.Add(i.ToString());
    }
    public IEnumerable<string> FilteredList
    {
        get { return this.items.Where(item => item.Contains(filter)).ToArray(); }
    }
    public string Filter
    {
        get { return filter; }
        set
        {
            if (filter != value)
            {
                filter = value;
                PropertyChanged(this, new PropertyChangedEventArgs("FilteredList"));
            }
        }
    }
    public event PropertyChangedEventHandler PropertyChanged = (s, e) => { };
}

网格中只有100个字符串。文本框允许过滤字符串。

但是,将例如123写入过滤器,然后再次删除它,将使应用程序冻结数秒。为什么这不是即时的?

编辑:在。net 4.5中,它确实是即时的,即使有10,000个项目。似乎是。net 4.6中的一个回归?

为什么在.net 4.6中更改WPF DataGrid ItemsSource如此之慢?

问题是每次都要替换整个集合。您应该使用CollectionViewSource作为DataGrid的源。CollectionViewSource接受过滤器表达式。因此,您可以基于原始IEnumerable创建一个CollectionViewSource,并基于文本框值创建一个过滤器方法。然后调用CollectionViewSource

的方法Refresh

DataGrid.EnableColumnVirtualization默认为False。