2012-09-03 77 views
10

我使用CodePlexBea Stollnitz的博客以及Vincent Da Ven Berhge的論文(同一鏈接)的一些想法實施了數據虛擬化解決方案。不過,我需要一種不同的方法,所以我決定寫我自己的解決方案。帶數據虛擬化的DataGrid行請求模式

我使用DataGrid來顯示大約一百萬行使用此解決方案。我也在使用UI虛擬化。我的解決方案是可行的,但在某些情況下,我在DataGrid如何從其源請求數據時遇到一些奇怪的行爲。

關於解決方案

我寫了一份清單,完成所有繁重的工作。它是一個通用類,名稱爲VirtualList<T>.它實現了ICollectionViewFactory接口,因此集合視圖創建機制可以創建一個​​實例來包裝它。這個類繼承自ListCollectionView。我沒有按照建議編寫自己的ICollectionView實現。繼承似乎也很好。

VirtualList<T>將整個數據分成頁面。它獲取總項目數,每當DataGrid通過列表索引器請求一行時,它會加載適當的頁面或從緩存中返回。頁面在內部被回收,並且在空閒時間處理未使用的頁面。

數據請求模式

  • 我學到的第一件事,是VirtualList<T>應該實現IList(非通用)。否則ItemsControl會將其視爲IEnumerable並查詢/枚舉所有行。這是合乎邏輯的,因爲DataGrid不是類型安全的,所以它不能使用接口IList<T>

  • 具有0索引的行經常被DataGrid詢問。它似乎被用於視覺項目測量(根據調用堆棧)。所以,我只是緩存這一個。

  • DataGrid中的高速緩存機制使用可預測的模式來查詢它顯示的行。首先它要求可見行從上到下(每行兩次),然後在可見區域(包括第一個可見行)下降之前查詢幾行(取決於可見區域的大小)從底部到頂部訂購。之後,它會在可見行(包括最後一個可見行)之後從上到下請求相同數量的行。

    如果可見行索引是4,5,6。數據請求將是:4,4,5,5,6,6,4,3,2,1,6,7,8,9。

    如果我的頁面大小設置正確,我可以從當前頁面和先前加載的頁面提供所有這些請求。

  • 如果CanSelectMultipleItemsTrue並且用戶選擇使用SHIFT鍵或鼠標拖動多個項目,則DataGrid枚舉從列表中選擇的端部的開始的所有行。無論IList是否實施,此枚舉都通過IEnumerable接口進行。

  • 如果所選行不可見並且當前可見區域與所選行相距「很遠」,則有時DataGrid會開始請求從選定行到可見區域結束的所有項目。包括它們之間甚至不可見的所有行。我無法弄清楚這種行爲的確切模式。也許我的實現是這個原因。

我的問題

  • 我很納悶,爲什麼DataGrid請求不可見行,因爲當成爲可見的那些行會再次請求?

  • 爲什麼有必要請求每行兩到三次?

  • 誰能告訴我如何使DataGrid不使用IEnumerable,除了關閉多項選擇?

回答

5

我至少找到了某種愚弄虛擬列表的方法。你可以閱讀它here

如果您發現了另一種解決方案(這比我的更好),請告訴我!

+0

是的,我最終做了類似的事情。我返回了我已經加載的所有物品,沒有其他物品。自那以後沒有造成問題。謝謝 –