【发布时间】:2012-08-16 11:50:46
【问题描述】:
我有一个将Sorted property 设置为true 的winforms TreeView 控件。我还通过将IComparer 的实例分配给TreeViewNodeSorter 属性来覆盖默认排序器。
不幸的是,使用AddRange 函数添加几千个节点可能需要 10 秒。如果我将 Sorted 设置为 false,则 AddRange 函数小于 1/2 秒。 (请不要讨论添加这么多节点的有效性)
啊哈,我听到你说.. 我的 IComparer 对象有问题。不是根据探查器。几乎没有时间花在排序对象上,但 AddRange 函数却在慢函数列表的顶部。
这个问题很容易在测试项目中复制。只需创建一个TreeNodes 列表,然后使用AddRange 函数将其添加到现有的展开树节点中。这将使用树文本上的默认排序 - 再次慢得不成比例。
为了演示如果我在测试 probject 中禁用 Sorted 属性并在我的节点列表上使用 List<T>.Sort 函数(带有比较节点文本的委托),然后再将它们添加到树几乎没有延迟。
这导致在使用AddRange 之前手动对节点进行排序的解决方法。没关系,但是在将节点添加到现有的子节点集时找到正确的插入点意味着需要做很多工作 - 而不是简单地将 Sorted 设置为 true。
有没有办法加快这种行为?
编辑 - 似乎唯一的方法是在添加之前进行排序。这有点麻烦,但我想出了以下扩展方法:
public static void AddSortedRange(this TreeNodeCollection existingNodes, IList<TreeNode> nodes, TreeView treeView, IComparer sorter)
{
TreeNode[] array = new TreeNode[nodes.Count + existingNodes.Count];
existingNodes.CopyTo(array, 0);
nodes.CopyTo(array, existingNodes.Count);
Array.Sort(array, sorter);
treeView.BeginUpdate();
existingNodes.Clear();
existingNodes.AddRange(array);
treeView.EndUpdate();
}
将现有节点复制到数组、附加新节点、对数组进行排序然后替换尝试在树视图中内联操作节点的操作更快 - 上述代码中最慢的操作是 existingNodes.Clear() 调用
【问题讨论】:
-
在添加之前排序如何?
-
你不能只在添加所有节点后才将 Sorted 设置为 true 吗?
-
@UweKeim - 如问题所述,在现有节点集中插入节点需要做大量额外工作 - 特别是将范围合并到现有集合中
-
@ken2k - 只是将延迟转移到 Sorted 属性.. 将 Sorted 保留为 false 并在 Add 之后调用 Sort() 函数很遗憾