WPF的UI虛擬化

許多時候,咱們的界面上會呈現大量的數據,如包含數千條記錄的表格或包含數百張照片的相冊。因爲呈現UI是一件開銷比較大的動做,一次性呈現數百張照片就目前的電腦性能來講是須要佔用大量內存和時間的。所以須要對其進行優化。之前採用的方案大多數是翻頁,翻頁在某種程度上形成用戶瀏覽的中斷,所以如今每每採用一種新的方案——UI虛擬化。html

UI虛擬化的原理是:可是因爲顯示器和人眼的限制,用戶每每只會同時看到其中的數十條數據,所以只要在界面上渲染用戶所看到的那些數據便可,對於用戶呈現的界面仍然是同樣的。微軟的MSDN文檔UI虛擬化說明的比較詳細,這裏就不累述了。windows

關於UI虛擬化的實現,其核心則是VirtualPanel,在WPF中內置的VirtualPanel貌似只有VirtualizingStackPanel一個,不過這個也是最實用的,通常經常使用於表格之類的數據呈現。若是須要其它佈局方式的Panel,則須要本身實現,MSDN Blog上有一系列文章介紹得比較詳細:瀏覽器

文章最後也附帶了一個VirtualizingTilePanel,實現了一個相似WrapPanel的效果(它要求裏面的元素大小是相等的)。用於照片瀏覽之類的持續仍是比較方便的,不知道爲何M$官方沒有帶這個。原文的.Net版本比較老,是直接編譯不過去的,須要自行修改一下。網絡

 

實現自定義VirtualizingPanel並不是很複雜,首先介紹介紹幾個前置條件:app

1. VirtualizingPanel是用於UI虛擬化的,它是用來作ItemsControl的ItemTemplate的,而不是像普通Panel那樣直接控制Children。所以,它必須同ItemsControl及其子類(如DataGrid、ListBox)搭配使用,並繼承自VirtualizingPanel。佈局

2. VirtualizingPanel是須要和ScrollViewer一塊兒使用的,沒有ScrolViewer的話,全部控件都是可見的,談不上虛擬化。須要注意的是,ItemsControl的默認Template沒有ScrollViewer,在ItemsControl中使用VirtualizingPanel時,須要修改一下Template,加上ScrollViewer,並設置CanContentScroll="True"。性能

3. UI虛擬化是須要在不呈現全部的UI控件前提下知道當前視圖下元素呈現效果的,若是全部的數據都轉換了爲控件的話,也就談不上虛擬化了。也就是說,不能靠Measure和Arrange全部子元素來肯定佈局。優化

 

具體實現的時候通常有以下幾個功能點:網站

  1. Panel須要實現IScrollInfo接口,這樣才能手動控制滾動時候的界面虛擬化。關於IScrollInfo接口,我前面的文章中有一些介紹,能夠參考一下。
  2. Panel須要能只根據數據感知總體的佈局。常見的有三種方案:1. 在Panel中直接指定每一個子元素所佔據的空間大小,2. 拿第一個子元素所佔據的大小來衡量其它子元素所佔據的大小,3.數據中直接聲明它所須要的大小
  3. Panel根據當前窗口的大小呈現元素(加載可見元素,刪除不可見元素)。

例子就能夠直接參考前面的那個,這裏就不單獨舉例了。spa

  

數據虛擬化:

UI虛擬化能夠解決渲染UI控件所須要較多的時間和內存的問題,可是仍是有能夠優化的空間,那就是全部的數據仍然都加載到了內存中了。咱們仍然能夠採用和UI虛擬化同樣的優化方案:不加載全部數據到集合,只加載用戶可見部分。數據虛擬化自己並不受WPF所支持,不過當咱們的Panel實現IScrollInfo接口了以後,就能夠精確感知滾動條了,實現數據虛擬化也不是難事。

通常來講,咱們不多使用數據虛擬化,主要的緣由是它大多數的時候只能減小不多一點內存佔用,反而帶來了較大的代碼複雜度, 通常是認爲得不償失的。

不過,有的時候,咱們的數據是來自於外部RPC訪問,這個時候數據虛擬化就有意義了,考慮以下兩個場景:

  1. 新聞客戶端,數據來源是來自於遠程的Rest服務,可是它的接口是分頁獲取的,只能每次獲取50條,總共卻可能有100頁。
  2. 圖片瀏覽器,圖片不是來自於本地,而是來自於圖片服務網站。

第一個例子就是比較典型的數據虛擬化的應用場景了,若是一開始就加載全部100頁新聞就須要花費大量時間了。第二個例子則是部分數據虛擬化,圖片信息無需虛擬化,但圖片呈現須要虛擬化,只是在須要呈現的時候才從網絡下載。

相關文章
相關標籤/搜索