ListView批量勾选性能优化:2800条Item设置Checked过慢求解
优化大量项ListView勾选状态更新的方案
你的问题核心在于每次设置ListViewItem.Checked都会触发控件重绘和相关事件,2800次重复操作会导致UI线程阻塞,耗时剧增。结合你的场景(默认全选,仅需保留指定5项勾选),可以从三个方向优化:
优化点1:用HashSet替代线性查找
原代码中oSecurities.FindSecurity是线性查找(假设SecurityList内部遍历匹配),2800次查找的时间复杂度是O(n*k)(n是ListView项数,k是目标列表长度)。把目标Symbol存入HashSet后,查找复杂度降为O(1),大幅减少判断耗时。
优化点2:暂停ListView绘制
通过BeginUpdate()和EndUpdate()方法暂停ListView的UI刷新,直到所有勾选状态修改完成后再一次性重绘,避免频繁的局部重绘开销。
优化点3:减少不必要的属性赋值
因为默认所有项都是勾选状态,你只需要把不在目标列表中的项取消勾选,无需重复设置已在目标列表中的项的Checked=true(它们本来就是勾选状态),进一步减少操作次数。
优化后的代码
public void NewCheckSecurities(SecurityList oSecurities) { // 参数校验 if (oSecurities == null || oSecurities.Count == 0) { // 如果目标列表为空,直接取消所有勾选 m_lsvSecurities.BeginUpdate(); foreach (ListViewItem oItem in m_lsvSecurities.Items) { oItem.Checked = false; } m_lsvSecurities.EndUpdate(); return; } // 将目标证券的Symbol存入HashSet,提升查找效率 HashSet<string> targetSymbols = new HashSet<string>(); foreach (SecurityItem item in oSecurities) { targetSymbols.Add(item.Security.Symbol); } // 暂停ListView绘制 m_lsvSecurities.BeginUpdate(); try { foreach (ListViewItem oItem in m_lsvSecurities.Items) { SecurityItem securityItem = oItem.Tag as SecurityItem; if (securityItem == null) continue; // 仅当项不在目标列表时,取消勾选(默认已勾选) if (!targetSymbols.Contains(securityItem.Security.Symbol)) { oItem.Checked = false; } } } finally { // 恢复绘制,一次性刷新UI m_lsvSecurities.EndUpdate(); } }
额外说明
- 如果你的
SecurityList不支持直接枚举内部项,可先遍历一次oSecurities,用FindSecurity取出所有目标Symbol存入HashSet,避免后续重复查找。 BeginUpdate()和EndUpdate()必须配对使用,放在try-finally块里能保证即使出现异常,控件也能恢复正常绘制状态。
内容的提问来源于stack exchange,提问作者DanLev
相关产品推荐
相关产品推荐

