WinForm的ListView在加载大量数据时会出现闪烁的问题,同时数据加载很慢。若是你的列表中有超过千条的数据且不作特殊处理仍是用普通的ListView.Items.Add(),估计你的用户得抱怨了。html
下面说下解决方法:windows
一、使用listView1.Items.AddRange()代替Add数组
这种方法须要先将数据放入一个缓存数组中,而后调用AddRange一次性加入ListView中,同时能够用一个计数器记录一次性加入缓存的数量,以下:缓存
listView1.Items.Clear(); if (vList.Count > 0) { int indexI = 0; List<ListViewItem> listBuffer = new List<ListViewItem>(); foreach (var item in vList) { ListViewItem li = new ListViewItem(); li.ImageIndex = 0; li.SubItems[0].Text = item.Name; li.Tag = item; li.ForeColor = item.Status == 0 ? Color.Green : Color.Red; listBuffer.Add(li); if (indexI++ % 1000 == 0) { listView1.Items.AddRange(listBuffer.ToArray()); listBuffer.Clear(); } if (indexI % 50 == 0) { Application.DoEvents(); } } listView1.Items.AddRange(listBuffer.ToArray()); }
这样能够减小ListView闪烁的次数,数据量不是很大时有效果。ide
二、自定义ListView类 this
下面这个类在网上广为流传,虽然解决了ListView闪烁的问题,可是在打开速度上和原来没什么区别,同时带来一个问题就是若是程序切换到别的ListView上,数据还会继续忘原来的ListView中添加,直到数据全面添加完成。 orm
public class ListViewLargeData : System.Windows.Forms.ListView { public ListViewLargeData() { this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true); this.SetStyle(ControlStyles.EnableNotifyMessage, true); } protected override void OnNotifyMessage(Message m) { if (m.Msg != 0x14) { base.OnNotifyMessage(m); } } }
三、开启ListView的VirtualMode模式htm
此方式也是本文重点推荐的方式,能够实现不闪烁效果,并且打开速度很快。每每好的效果带来的问题是代码较为复杂,具体写法能够看官方示例http://msdn.microsoft.com/zh-cn/library/system.windows.forms.listview.virtualmode.aspx,或者http://www.cnblogs.com/hcfalan/archive/2008/07/08/1238493.html,下面说下须要注意的几点: blog
(1)必须设置VirtualMode为true并设置VirtualListSize大小 事件
listView1.VirtualMode = true;
listView1.VirtualListSize = bufferItems.Count;
listView1.RetrieveVirtualItem += new RetrieveVirtualItemEventHandler(listView_RetrieveVirtualItem);
(2)绑定该事件为ListView计算Item
void listView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
{
e.Item = m_hListViewItems[e.ItemIndex];
}
(3)若是中间更新了数据须要从新设置VirtualListSize,并调用Invalidate()方法(此方法并不是必须请高手指点)。
listView1.VirtualListSize = bufferItems.Count;
listView1.Invalidate();
(4)禁用selectedItem,在该模式下使用selectedItem将产生异常,能够用下面方法代替
private List<ListViewItem> FindSelectedAll() { List<ListViewItem> r = new List<ListViewItem>(); foreach (int item in listView1.SelectedIndices) { r.Add(bufferItems[item]); } return r; }