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页新闻就须要花费大量时间了。第二个例子则是部分数据虚拟化,图片信息无需虚拟化,但图片呈现须要虚拟化,只是在须要呈现的时候才从网络下载。

相关文章
相关标签/搜索