4

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

有什么想法和技巧可以让它更快吗?

编辑:

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

3 回答 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();
于 2012-10-11T08:35:50.717 回答
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();
于 2012-10-11T08:38:24.063 回答
0

ListView 将为从列表中删除的每个项目触发一个事件。您可以尝试通过清除整个 ListView 来避免这种情况,然后立即添加一个新的项目列表,该列表会删除您想要删除的 100 个项目。这只会触发少数事件。

于 2012-10-11T04:53:10.760 回答