2012-05-09 52 views
2

對於Winforms應用程序中的虛擬ListView控件,什麼是ALL RetrieveVirtualItem事件的功能?什麼是ListView.RetrieveVirtualItem事件 - C#

場景:有一個Dictionary對象充當我的ListView緩存。其項目顯示在ListView上。單擊列時,緩存字典將在內存中排序,而ListView將被刷新()。對UI的影響,ListView排序良好。 :)

但我想了解RetrieveVirtualItem事件的作用是什麼,它在Refresh()上觸發。

在RetrieveVirtualItem事件處理[別人的代碼,:(],下面是完成:

  1. 基於RetrieveVirtualItemEventArgs.ItemIndex,從Cache中獲得
  2. 設置RetrieveVirtualItemEventArgs.Item = retreived項目上述消息

看來事件處理程序中做了什麼很重要,因爲如果我把它拿出來,ListView會哭。這個事件的意義是什麼?

編輯 或讓我重新提出問題......我的擔心是,爲什麼在排序(和RetrieveVirtualItem事件處理程序)後,所選項目仍保留在排序前的位置。即,如果我選擇項目#5並進行排序,並且如果排序使該項目成爲最後一個項目,則我希望在排序之後選擇最後一個項目。但在我的情況下,排序後選擇第5項。那麼RetrieveVirtualItem WRT選擇的項目的默認行爲是什麼?

回答

2

虛擬列表視圖只處理索引。因此,如果在排序之前選擇了第5個項目,排序後仍然會選擇第5個項目。控制本身無法知道原來位於第5行的數據現在位於第一行。

你會在你的排序方法,程序,對於自己:

  1. 記得選擇哪些項目(記住:你不能在虛擬模式,當使用SelectedItems屬性)
  2. 做排序
  3. 找到以前選定的項目的索引現在住
  4. 選擇那些指數

您可以在ObjectListView中看到所有這些行爲 - 圍繞標準.NET ListView的包裝。

2

RetrieveVirtualItem事件僅在ListView進入虛擬模式時使用。在Item集合中保留ListViewItems(而不是在虛擬模式下)時,它會在需要時動態創建ListViewItems。

如果您不處理RetrieveVirtualItem事件,則不會將ListViewItems添加到您的ListView中。我已附加一些示例代碼編寫爲處理所述事件的典型方法:

//Dynamically returns a ListViewItem with the required properties; in this case, the square of the index. 
void listView1_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e) 
    { 
     //Check if cache has been instantiated yet, and if so, whether the item corresponding to the index requested has been added to the cache already 
     if (myCache != null && e.ItemIndex >= firstItem && e.ItemIndex < firstItem + myCache.Length) 
     { 
      //Return cached item for index 
      e.Item = myCache[e.ItemIndex - firstItem]; 
     } 
     else 
     { 
      //When item not in cache (or cache not available) return a new ListViewItem 
      int x = e.ItemIndex * e.ItemIndex; 
      e.Item = new ListViewItem(x.ToString()); 
     } 
    } 

這個例子是從MSDN(http://msdn.microsoft.com/en-us/library/system.windows.forms.listview.virtualmode(v=vs.90).aspx)其中進一步的細節可以發現服用。

+0

你說:「如果你不處理RetrieveVirtualItem事件則沒有ListViewItems將被添加到您的ListView」,等等,相反,它意味着所有的項目是由這個事件添加?似乎不,因爲它只能用'myCache [e.ItemIndex - firstItem]'。 – ViV

+0

是的,所有項目(當listview處於虛擬模式時)都會被這個事件添加。該方法不僅依賴於從myCache中獲取項目,就像執行else子句中的代碼一樣,新項目被實例化並分配給事件args(e.Item = new ListViewItem())。另一個事件CacheVirtualItems依賴於管理緩存 – Richard

4

虛擬ListView應該只爲屏幕上當前可見的行調用RetreiveVirtualItem。

當您在ListView中導航時,例如,您按下頁面向下鍵,ListView將計算現在應該是最上面一行的索引,然後調用RetrieveVirtualItem,以便您的代碼可以提供要使用的項目在每一行索引處。

除非您通過RetrieveVirtualItem緩存或以其他方式存儲您正在提供的項目,否則它們將在滾動出列表視圖後不再存在。

這就是VirtualListView中的Virtual意味着什麼 - 沒有任何實際的行,行是虛擬的。這就是它如何顯示一個包含數十萬行的列表 - 因爲它只能實際包含在屏幕上可見的行數。

實際上,ListView就像是一個正在上下移動內部數據列表的窗口 - RetreiveVirtualItem方法就是它調用的將物品移動到窗口中移動的窗口。它說,嘿,我剛剛搬到第15行 - 給我那個行的項目。它將繼續爲每個可見的行索引調用RetreiveVirtualItem。如果ListView在屏幕上的高度爲5行,那麼即使支持listview的實際數據有3000個項目,您也會收到5次對RetrieveVirtualItem的調用。每當ListView的最上一行發生更改時(由於導航),您將收到5次對RetrieveVirtualItem的調用(這並非總是如此,但它是正確的想法 - 例如,如果向下滾動一行,它將簡單請求您提供最後一行 - 它也將放棄用於滾動查看的舊頂部行的數據)。

我猜如果我們假設ListView在顯示屏上只有一行高(意味着屏幕上只有一行實際可見),那麼解釋起來可能更容易 - 當您向上或向下移動ListView數據列表(即用戶瀏覽ListView),它每次移動到新行時都會調用RetrieveVirtualItem一次。

希望幫助... 好運