一、前言
虛擬模式在許多情況下都很有用。 如果必須從已存在於內存中的非常大的集合填充一個 ListView 對象,則為每項創建一個 ListViewItem 對象會很浪費。 在虛擬模式下,從緩沖之中獲取所需的數據進行加載,性能會有很大提高。 在其他情況下,可能需要經常重新計算 ListViewItem 對象的值,對整個集合進行此操作將產生不可接受的性能。
如下為虛擬模式的一個應用示例(仿VS2010錯誤列表),截圖如下:
二、虛擬模式相關注意點
1、設置一個緩存屬性,來保存需要加載的數據:
protected List<ListViewItem> CurrentCacheItemsSource
{
get;
private set;
}
2、通過虛擬模式來加載數據,如下:
private void LoadListViewItems(List<ListViewItem> items) { listView.Items.Clear(); if (items == null) { stripStatusInfo.Text = "當前總共記錄數為:0"; return; } listView.GridLines = true; listView.FullRowSelect = true; listView.View = View.Details; listView.Scrollable = true; listView.MultiSelect = false; listView.HeaderStyle = ColumnHeaderStyle.Clickable; listView.Visible = true; listView.VirtualListSize = items.Count; listView.VirtualMode = true; listView.RetrieveVirtualItem += new RetrieveVirtualItemEventHandler(listView_RetrieveVirtualItem); stripStatusInfo.Text = "當前總共記錄數為:" + items.Count; }
listView.VirtualMode = true;//設置虛擬模式
listView.VirtualListSize = items.Count;//設置虛擬列表容量大小
listView.RetrieveVirtualItem += new RetrieveVirtualItemEventHandler(listView_RetrieveVirtualItem);//綁定虛擬操作
3、在RetrieveVirtualItem方法中加載相關的數據:
void listView_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) { if (this.CurrentCacheItemsSource == null || this.CurrentCacheItemsSource.Count == 0) { return; } e.Item = this.CurrentCacheItemsSource[e.ItemIndex]; if (e.ItemIndex == this.CurrentCacheItemsSource.Count) { this.CurrentCacheItemsSource = null ; } }
需要注意及時釋放掉所需要的緩存數據,如下:
if (e.ItemIndex == this.CurrentCacheItemsSource.Count)
{
this.CurrentCacheItemsSource = null ;
}
當e.ItemIndex 的值與緩存中的集合大小相等時,設置緩存為NULL(對象根引用設置為NULL,內存中的對象不再有根引用,所需的內存將由GC第二次回收時釋放,相關內容請查看CLR GC)。
三、總結
當數據為幾萬條記錄時,加載ListView速度非常快,不會造成任何影響,頁面顯示正常。目前,測試30W條簡單的記錄,性能還是可以接受的。當然,對於大數據量而言(50W條記錄以上),分頁才是最佳方式。其次,需要注意的是,對緩存數據需要及時清空,避免不必要的性能損失。
源代碼下載:ListView虛擬模式源碼
http://files.cnblogs.com/jasenkin/Jasen.Framework.WinApp.rar
作者:JasenKin
出處:http://www.cnblogs.com/jasenkin/