WPF的UI虚拟化
许多时候,我们的界面上会呈现大量的数据,如包含数千条记录的表格或包含数百张照片的相册。由于呈现UI是一件开销比较大的动作,一次性呈现数百张照片就目前的电脑性能来说是需要占用大量内存和时间的。因此需要对其进行优化。以前采用的方案大多数是翻页,翻页在某种程度上造成用户浏览的中断,因此现在往往采用一种新的方案——UI虚拟化。
UI虚拟化的原理是:但是由于显示器和人眼的限制,用户往往只会同时看到其中的数十条数据,因此只要在界面上渲染用户所看到的那些数据即可,对于用户呈现的界面仍然是一样的。微软的MSDN文档UI虚拟化说明的比较详细,这里就不累述了。
关于UI虚拟化的实现,其核心则是VirtualPanel,在WPF中内置的VirtualPanel貌似只有VirtualizingStackPanel一个,不过这个也是最实用的,一般常用于表格之类的数据呈现。如果需要其它布局方式的Panel,则需要自己实现,MSDN Blog上有一系列文章介绍得比较详细:
文章最后也附带了一个VirtualizingTilePanel,实现了一个类似WrapPanel的效果(它要求里面的元素大小是相等的)。用于照片浏览之类的持续还是比较方便的,不知道为什么M$官方没有带这个。原文的.Net版本比较老,是直接编译不过去的,需要自行修改一下。
实现自定义VirtualizingPanel并非很复杂,首先介绍介绍几个前置条件:
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所有子元素来确定布局。
具体实现的时候一般有如下几个功能点:
- Panel需要实现IScrollInfo接口,这样才能手动控制滚动时候的界面虚拟化。关于IScrollInfo接口,我前面的文章中有一些介绍,可以参考一下。
- Panel需要能只根据数据感知整体的布局。常见的有三种方案:1. 在Panel中直接指定每个子元素所占据的空间大小,2. 拿第一个子元素所占据的大小来衡量其它子元素所占据的大小,3.数据中直接声明它所需要的大小
- Panel根据当前窗口的大小呈现元素(加载可见元素,删除不可见元素)。
例子就可以直接参考前面的那个,这里就不单独举例了。
数据虚拟化:
UI虚拟化可以解决渲染UI控件所需要较多的时间和内存的问题,但是还是有可以优化的空间,那就是所有的数据仍然都加载到了内存中了。我们仍然可以采用和UI虚拟化一样的优化方案:不加载所有数据到集合,只加载用户可见部分。数据虚拟化本身并不受WPF所支持,不过当我们的Panel实现IScrollInfo接口了之后,就可以精确感知滚动条了,实现数据虚拟化也不是难事。
一般来说,我们很少使用数据虚拟化,主要的原因是它大多数的时候只能减少很少一点内存占用,反而带来了较大的代码复杂度, 一般是认为得不偿失的。
不过,有的时候,我们的数据是来自于外部RPC访问,这个时候数据虚拟化就有意义了,考虑如下两个场景:
- 新闻客户端,数据来源是来自于远程的Rest服务,但是它的接口是分页获取的,只能每次获取50条,总共却可能有100页。
- 图片浏览器,图片不是来自于本地,而是来自于图片服务网站。
第一个例子就是比较典型的数据虚拟化的应用场景了,如果一开始就加载所有100页新闻就需要花费大量时间了。第二个例子则是部分数据虚拟化,图片信息无需虚拟化,但图片呈现需要虚拟化,只是在需要呈现的时候才从网络下载。
WPF的UI虚拟化的更多相关文章
- 【WPF】UI虚拟化之------自定义VirtualizingWrapPanel
原文:[WPF]UI虚拟化之------自定义VirtualizingWrapPanel 前言 前几天QA报了一个关于OOM的bug,在排查的过程中发现,ListBox控件中被塞入了过多的Item,而 ...
- WPF listbox UI虚拟化
ListBox 默认是UI虚拟化的. 1. 原生使用 <ListBox VirtualizingPanel.IsVirtualizing="True" Virtualiz ...
- WPF之UI虚拟化
在WPF应用程序开发过程中,大数据量的数据展现通常都要考虑性能问题.有下面一种常见的情况:原始数据源数据量很大,但是某一时刻数据容器中的可见元素个数是有限的,剩余大多数元素都处于不可见状态,如果一次性 ...
- wpf 客户端【JDAgent桌面助手】开发详解(三) 瀑布流效果实现与UI虚拟化优化大数据显示
目录区域: 业余开发的wpf 客户端终于完工了..晒晒截图 wpf 客户端[JDAgent桌面助手]开发详解-开篇 wpf 客户端[JDAgent桌面助手]详解(一)主窗口 圆形菜单... wpf 客 ...
- WPF多线程UI更新——两种方法
WPF多线程UI更新——两种方法 前言 在WPF中,在使用多线程在后台进行计算限制的异步操作的时候,如果在后台线程中对UI进行了修改,则会出现一个错误:(调用线程无法访问此对象,因为另一个线程拥有该对 ...
- windowsphone 瀑布流&ui虚拟化
瀑布流已经有点年代了吧,不过wp上还真是挺少资料的.今天抽空把自己之前搞过的东西写出来,避免大家重复劳动. 一.简单的瀑布流排版加入ui虚拟化. 最近看了 段博琼 ui虚拟化的一篇博文,链接:htt ...
- WPF Modern UI 主题更换原理
WPF Modern UI 主题更换原理 一 . 如何更换主题? 二 . 代码分析 代码路径 : FirstFloor.ModernUI.App / Content / SettingsAppeara ...
- WPF 模拟UI 键盘录入
原文:WPF 模拟UI 键盘录入 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/yangyisen0713/article/details/1835 ...
- (转)基于 WPF + Modern UI 的 公司OA小助手 开发总结
原文地址:http://www.cnblogs.com/rainlam163/p/3365181.html 前言: 距离上一篇博客,整整一个月的时间了.人不能懒下来,必须有个阶段性的总结,算是对我这个 ...
随机推荐
- $(document).ready 和 window.onload 的区别
1.相同点 两者都用于在网页加载完后执行相应代码块. 2.不同点 window.onload 在创建完 DOM 树后,所有外部资源(图片.Flash 动画等)加载完成,且整个页面在浏览器窗口中显示完毕 ...
- 需要重刷整個 image 的時機 - 1
最近遇到一個問題, gpio 讀出來的值與預期不同, 詳細描述如下: 首先手機 download 了一個完整的 daily build image , 接下來 不斷地修改 kernel 部分 code ...
- MySQL数据库分表分区(一)(转)
面对当今大数据存储,设想当mysql中一个表的总记录超过1000W,会出现性能的大幅度下降吗? 答案是肯定的,一个表的总记录超过1000W,在操作系统层面检索也是效率非常低的 解决方案: 目前针对 ...
- 重装系统备份MYSQL数据(整库备份)
今天要重装Windows 8系统,但是我的Mysql里面数据太多,要备份成sql文件实在太麻烦,于是我听说可以直接拷贝数据文件夹,所以就试了,结果还成果了. 具体如下: 我安装的时候把数据文件夹就放在 ...
- linux命令(9):route命令
查看路由表:route –n //添加到主机的路由 # route add –host 192.168.168.110 dev eth0 # route add –host 192.168.168.1 ...
- Sqrt(x)——二分法,防越界
Implement int sqrt(int x). Compute and return the square root of x. 转自:http://blog.csdn.net/doc_sgl/ ...
- Razor 部分页面
最近在和师父一起打野,后台要求挺多的.后台还是用的EF和MVC5,页面使用的razor. 现在是发现好多的页面有太多重复的东西了. 比如说查询页面的字段,比如说列表页,比如说详情方法都有. 灵机一动, ...
- vue-touch不支持vue2.0的替换方法
当你想用vue-touch时,却发现官网这句话 Touch events plugin for Vue.js. This plugin does not support Vue 2.0 yet. 但是 ...
- SpringBoot学习:读取yml和properties文件的内容
一.在SpringBoot实现属性注入: 1).添加pom依赖jar包: <!-- 支持 @ConfigurationProperties 注解 --> <!-- https://m ...
- 转:json注入
现在大部分web采用ajax通信,数据表现为json格式,因此可以尝试进行json注入. json注入:根据实际情况进行注入.有的时候,可能是为了方便,有人会手动拼接下JSON,但是这种随手代码,却可 ...