如何解决ListView更新时UI频繁闪烁的问题
解决ListView更新时UI频繁闪烁的问题
我太懂这种ListView疯狂闪烁的糟心体验了!本质上是因为你每次更新都在频繁触发UI重绘,加上默认的控件绘制机制没做批量优化,才导致了这种晃眼的效果。结合你给出的代码片段,给你几个立竿见影的解决办法:
1. 给ListView启用双缓冲
双缓冲的核心逻辑是让控件先在内存里完成所有绘制操作,再一次性把结果渲染到屏幕上,避免逐行绘制带来的闪烁。不过系统自带的ListView的DoubleBuffered属性是受保护的,你可以通过两种方式开启:
- 如果你是自己写的自定义ListView控件,直接在构造函数里加:
this.DoubleBuffered = true;
- 如果用的是工具箱拖进来的默认ListView,用反射来设置(建议在窗体初始化的时候执行一次就行):
typeof(ListView).InvokeMember( "DoubleBuffered", BindingFlags.SetProperty | BindingFlags.Instance | BindingFlags.NonPublic, null, listView3, new object[] { true } );
2. 批量更新时暂停控件重绘
你现在的逻辑是先清空ListView,再逐个添加驱动器项——每一次清空、每添加一个项都会触发一次重绘,累积起来就闪得厉害。用BeginUpdate()和EndUpdate()把你的更新逻辑包裹起来,就能让控件在这段时间内不重绘,直到所有操作完成后一次性渲染:
修改你的代码如下:
if (text.StartsWith("fdrivel§")) //客户端发送驱动器列表 { String data = text.Split('§')[1]; //获取驱动器列表 listView3.BeginUpdate(); // 暂停重绘 try { LvClear(listView3); //清空驱动器ListView foreach (String drive in data.Split('\n')) //遍历驱动器 { // 记得跳过空字符串,避免添加无效项 if (!string.IsNullOrWhiteSpace(drive)) { listView3.Items.Add(drive); } } } finally { listView3.EndUpdate(); // 恢复重绘,一次性渲染所有更改 } }
用try...finally包裹是为了确保哪怕中间出现异常,控件也能恢复重绘状态,不会一直卡住。
3. 优化你的LvClear方法
如果你的LvClear是通过循环逐个删除ListView项实现的,那也会触发多次重绘。建议直接替换成listView3.Items.Clear()——这个方法内部已经做了批量优化,比手动循环删除高效得多,还能减少闪烁。
总结
优先用BeginUpdate()/EndUpdate()包裹批量操作,再加上双缓冲设置,基本上就能解决你当前遇到的闪烁问题。如果之后要处理更大数据量的文件列表,还可以考虑用ListView的虚拟模式(VirtualMode),不过对你现在的场景来说,前面两个方法已经足够啦。
内容的提问来源于stack exchange,提问作者Jeremy Griffin
相关产品推荐
相关产品推荐

