4

私はすでに and を使用listView.BeginUpdate()しています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 に答える