WinForm ListView不分頁加載大量數據

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;         }

相關文章
相關標籤/搜索