【问题标题】:How to improve Sorting performance on a None-Virtualized DataGrid?如何提高非虚拟化 DataGrid 的排序性能?
【发布时间】:2011-09-01 16:10:21
【问题描述】:

我相信你们中的大多数人现在会惊讶于为什么我们必须关闭 wpf 数据网格的虚拟化。虽然虚拟化确实有助于减少内存占用,但它会增加 CPU 开销,并且滚动体验并非完美无缺。

由于客户的要求,我们不得不禁用数据网格中的虚拟化并进一步优化它,现在它可以非常平滑地上下滚动,没有任何延迟。缺点是数据是预先加载并保存在内存中的。这是我们可以接受的解决方案。

然而,排序现在已成为一个大问题。虽然使用 CustomSorter : IComparer 确实是比通常的 SortDecriptors 更好的排序替代方案,但在我们的案例中它几乎没有任何区别,尽管整个行都被重绘了。

有什么方法可以提高非虚拟化数据网格的排序速度?

非常感谢,

更新:

我遇到了一个想法,我正在努力实施。解除绑定 Itemssource,进行排序,排序完成后,重新绑定 Itemssource。

为了实现这一点,我从 DataGrid 派生来捕获 SortHandler(即用户单击列时)

public class CustomSortDataGrid : DataGrid
    {
        public CustomSortDataGrid()
        {
            Sorting += SortHandler;
        }

        private void SortHandler(object sender, DataGridSortingEventArgs e)
        {
            DataGridColumn column = e.Column;
            IComparer comparer = null;

            // prevent the built-in sort from sorting
            e.Handled = true;

            ListSortDirection direction = (column.SortDirection != ListSortDirection.Ascending) ? ListSortDirection.Ascending : ListSortDirection.Descending;

            //set the sort order on the column
            column.SortDirection = direction;

            //use a ListCollectionView to do the sort.
            var lcv = (ListCollectionView)CollectionViewSource.GetDefaultView(ItemsSource);


            comparer = new BidYieldComparer(direction);

            //apply the sort
            lcv.CustomSort = comparer;

        }
    }

这将利用优于 SortDescriptors 的更快的比较器排序。 现在的问题是我在什么阶段取消绑定项目排序,应用排序,等待排序,一旦事件(哪个?)触发然后将 Itemssource 重新绑定到视图。

BindingOperations.ClearBinding(this, ItemsSourceProperty);

上面的这一行将清除绑定。

//apply the sort
            lcv.CustomSort = comparer;

理论上(不确定这是否正确)ItemsSource = lcv;会重新绑定它。但是性能还是一样的。 :(

有人知道吗?

【问题讨论】:

  • 在您的网格中实现分页 :) 您显示了多少数据?一些第三方网格的排序速度非常快,如果预算允许,您至少应该尝试一下。
  • Microsoft WPF Datagrid 被广泛低估。我们已从 Xceed 切换到后者,因为您无法在 Xceed 中禁用虚拟化。我们需要 Excel 体验,而大多数第三方都不够快,无法处理这个问题。甚至没有基础设施。分页也不起作用,因为它带走了滚动功能。

标签: c# .net wpf sorting datagrid


【解决方案1】:

尝试先对您的集合进行排序,然后将排序后的集合绑定到您的 DataGrid。排序操作的速度取决于您将使用的排序算法。我曾经使用 插入排序算法,您可以在 http://en.wikipedia.org/wiki/Insertion_sort 中了解该算法。我很快就会给你发一个例子。

更新

你可以找到VB.Net实现here

你可以找到C#实现here

【讨论】:

  • 你可以使用VB.Net写的代码miroprocessor.blogspot.com/2011/05/…
  • 您好,谢谢。但是这个算法比 IComparer 快多少呢?
  • 两年前的@Kave 我想对一个庞大且非常复杂的集合进行排序,我尝试了包括IComparer在内的许多解决方案,但最好的时间是我使用插入排序算法。
  • @Kave 如果有帮助,请选择它作为答案或至少投票,谢谢
  • @Kave 这是我的代码的 C# 版本,希望对您有所帮助。 miroprocessor.blogspot.com/2011/06/…
【解决方案2】:

我猜这里的性能问题不是排序,而是绑定和重新绑定本身。

只需清除绑定并重新绑定您的网格。与排序相比,您应该不会看到太大的差异。

如果是这种情况,您可以尝试简化该网格的模板和样式(如果您正在使用)。

【讨论】:

    猜你喜欢
    • 2014-08-02
    • 1970-01-01
    • 1970-01-01
    • 2011-11-16
    • 2010-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-20
    相关资源
    最近更新 更多