最近在項目里面碰到最頭疼的一個難題就是Listbox虛擬化的問題,查閱很多文檔其實Listbox本身是支持虛擬化的,那么在什么情況下會破壞Listbox的虛擬化呢?目前我接觸到的主要有兩個原因:一.是需要在Listbox的ItemTemplate模板里面承載更多的顯示內容,因此我們將不再使用默認顯示模板(VirtualizingStackPanel),比如我們需要在Listbox每一項里面包含一張圖片同時下面顯示一行說明文字,遇到這種情況,我們可能會這樣去定義Listbox的模板項:
由於StackPanel容器控件本身是不支持虛擬化的,因此這就會間接地破壞Listbox的虛擬化。還有一種就是有的時候我們需要實現下拉刷新的效果,由於Listbox本身是沒有提供那種刷新的效果的,所以我們往往會根據Listbox里面拉動的距離來計算是否拉動到底部或者頂部,因此我們需要重寫一個繼承自Listbox的用戶自定控件,但是當我們運用用戶自定義控件的時候,我們測試發現這種情況下也已經破壞了Listbox的虛擬化,那么是為什么呢?按道理我們的自定義控件是從Listbox集成而來,可是為什么卻沒有Listbox默認的虛擬化效果呢?本人自己推測如下,因為有的時候我們去實現VirtualizingStackPanel模板屬性,即使有的時候會想到去實現,但是實現的方式可能又跟系統提供的有出入(這塊不太嚴謹,本人沒有自測)。
那么有沒有什么好的辦法可以避免以上原因所帶來的Listbox虛擬化破壞呢?在網上找了好久,發現好多人都采用LongListSelector控件去代替Listbox控件,沒錯LongListSelector默認情況下也是支持虛擬化的,並且即使改變它的內部默認模板,它的虛擬化也是不會被破壞的,但是在實際的運用當中本人還遇到一個比較頭疼的問題,就是:LongListSelector要顯示的內容是從Web上面下載而來的時候,我們會遇到一個異常:
Layout cycle detected. Layout could not complete.
這到底是什么原因引起的呢?大體意思是:界面檢測的時候,沒有完成。可是為什么重新檢測界面呢?網上找了一些資料發現:原來進行Web請求的時候,會有一定的時間延遲。在數據返回到客戶端得到處理之前,LongListSelector里面的Image控件已經得到初始化了,當真正的網絡回來之后,客戶端需要重新去處理數據,這個時候得到的真正的數據(例如圖片),他們的大小可能是不相同,LongListSelector要展示他們就需要重新給計算控件大小,分配合適的空間大小,這個時候就會一起上面我們說到的異常。那么有沒有什么好的辦法去處理這種異常呢?網上好多人的處理方法是:固定Image空間的大小,給它設置固定的Height和Width,但是本人試了一下,貌似還是不可以的。針對這塊本人還沒有找到什么好的解決方案,如果讀者有什么高見的話,歡迎與我聯系。