如何加速 Winforms ListView 的项目删除?

4

我已经使用 listView.BeginUpdate()listView.EndUpdate(),但是当我删除例如25000个项目中的100个项目时,仍然需要大约10秒钟的时间。

有没有任何想法或技巧可以让它更快?

编辑:

this.listView.BeginUpdate();
for (int i = this.listView.CheckedItems.Count - 1; i > -1; --i)
{
    this.listView.CheckedItems[i].Remove();
}
this.listView.EndUpdate();

2
你真的需要一次性加载25k个项目吗?分页或滚动加载怎么样? - user900202
展示给我代码,我可以在毫秒内删除100个项目。刚刚检查了代码,我是通过绑定实现的。 - Jeremy Thompson
用户可以向前或向后滚动,并随机查看列表部分,因此我不知道如何针对此进行优化。 - Joan Venge
1
我讨厌WinForms的缓慢。结果呢?最终转而使用C++。 - user541686
1
顺便提一下,您可能想尝试一下ListView的“虚拟模式”。 - user541686
显示剩余6条评论
3个回答

3
你可以从这里开始进行优化:
List<int> toRemove = new List<int>();

foreach (ListViewItem item in this.listView.Items)
{
    if (item.Checked) // check other remove conditions here
        toRemove.Add(item.Index);
}

/* sort indices descending, so you'll remove items with higher indices first
   and they will not be shifted when you remove items with lower indices */
toRemove.Sort((x, y) => y.CompareTo(x));
/* in this specific case you can simply use toRemove.Reverse(); 
   or iterate thru toRemove in reverse order
   because it is already sorted ascending.
   But you might want to force sort it descending in some other cases.
*/

this.listView.BeginUpdate();

foreach (int itemIndex in toRemove)
    this.listView.Items.RemoveAt(itemIndex); // use RemoveAt when possible. It's much faster with large collections

this.listView.EndUpdate();

0
这是因为每当你从Items中移除元素时,ListView必须找到该项(遍历列表来实现)并刷新CheckedItems集合(再次迭代所有剩余的项),所以复杂度是O^2。
最简单的方法是缓存SelectedIndices并使用listItem.Items.RemoveAt():
var selectedIndices = listView.SelectedIndices.Cast<int>().Reverse().ToList();
listView.BeginUpdate();
foreach (var index in selectedIndices) {
    listView.Items.RemoveAt(index);
}
listView.EndUpdate();

如果您不想使用Cast<>扩展方法,您可以将第一行替换为:

List<int> oToDelete = new List<int>(SelectedIndices.Count);
foreach (int iX in SelectedIndices)
{
   oToDelete.Add(iX);
}
oToDelete.Reverse();

谢谢,但是listView似乎没有RemoveAt方法。 - Joan Venge
好的,我找到了,它在items里面,但是转换崩溃了。 - Joan Venge

0
ListView将为从列表中删除的每个单独项目触发一个事件。您可以尝试通过清除整个ListView,然后一次添加一个新的项目列表来避免这种情况,该列表剥离了您想要删除的100个项目。这将仅触发少量事件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接