ListView批量添加条目时报“无法在多处添加或插入同一项”错误如何解决
报错原因
你写的问题代码存在两个核心错误,直接触发了该报错:
- 实例化
ListView.ListViewItemCollection时传入了listView1作为参数,相当于该集合已经和当前ListView绑定,你往集合里添加的所有项默认已经归属到listView1,后续再调用listView1.Items.AddRange(new_row)等于把已经属于该控件的项重复插入,直接触发 "Cannot add or insert the item in more than one place" 报错。 - 你的添加逻辑把单行的5个字段分别当成了独立的ListView条目插入,最终会导致1行数据拆成5行显示,不符合多列ListView的结构要求。
修复&优化方案
提升ListView批量插入速度的核心是减少控件重绘次数,不要每加一个条目就触发一次控件刷新,正确实现代码如下:
最优批量插入写法
建议一次性攒完所有要插入的条目后统一插入,性能提升最明显:
private void OtherFunction() { // 第一步:暂停ListView重绘,这是提升插入速度最核心的配置 listView1.BeginUpdate(); listView1.ListViewItemSorter = null; // 你的原有拉取数据的foreach循环逻辑 List<ListViewItem> itemsToAdd = new List<ListViewItem>(); foreach(/* 你的数据遍历逻辑 */) { // 构造单条多列条目 ListViewItem item = new ListViewItem(Event_Date); item.SubItems.AddRange(new string[]{Acc_Name, Client_IP, Event_DC, Failure_Code}); itemsToAdd.Add(item); } // 一次性插入所有条目 listView1.Items.AddRange(itemsToAdd.ToArray()); // 恢复控件重绘 listView1.EndUpdate(); }
保留单条添加方法的写法
如果你需要保留单独调用Add_To_List的逻辑,修改为如下实现即可:
private void Add_To_List(string date, string user, string ip, string domain, string lockedout) { ListViewItem item = new ListViewItem(date); item.SubItems.AddRange(new string[]{user, ip, domain, lockedout}); listView1.Items.Add(item); }
注意:如果是循环调用该方法,一定要把BeginUpdate()和EndUpdate()放在循环外层调用,不要在方法内部反复调用这两个方法,否则无法实现性能优化。
额外性能优化建议
如果你的单批插入条目超过1000条,可以开启ListView的虚拟模式:设置VirtualMode = true,自行维护数据源,通过VirtualListSize设置总条目数,在RetrieveVirtualItem事件中返回对应位置的条目,渲染性能会有数量级的提升。
内容的提问来源于stack exchange,提问作者Babyhamsta
相关产品推荐
相关产品推荐

