许多时候,我们的界面上会呈现大量的数据,如包含数千条记录的表格或包含数百张照片的相册。由于呈现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所有子元素来确定布局。

具体实现的时候一般有如下几个功能点:

  1. Panel需要实现IScrollInfo接口,这样才能手动控制滚动时候的界面虚拟化。关于IScrollInfo接口,我前面的文章中有一些介绍,可以参考一下。
  2. Panel需要能只根据数据感知整体的布局。常见的有三种方案:1. 在Panel中直接指定每个子元素所占据的空间大小,2. 拿第一个子元素所占据的大小来衡量其它子元素所占据的大小,3.数据中直接声明它所需要的大小
  3. Panel根据当前窗口的大小呈现元素(加载可见元素,删除不可见元素)。

例子就可以直接参考前面的那个,这里就不单独举例了。

数据虚拟化:

UI虚拟化可以解决渲染UI控件所需要较多的时间和内存的问题,但是还是有可以优化的空间,那就是所有的数据仍然都加载到了内存中了。我们仍然可以采用和UI虚拟化一样的优化方案:不加载所有数据到集合,只加载用户可见部分。数据虚拟化本身并不受WPF所支持,不过当我们的Panel实现IScrollInfo接口了之后,就可以精确感知滚动条了,实现数据虚拟化也不是难事。

一般来说,我们很少使用数据虚拟化,主要的原因是它大多数的时候只能减少很少一点内存占用,反而带来了较大的代码复杂度, 一般是认为得不偿失的。

不过,有的时候,我们的数据是来自于外部RPC访问,这个时候数据虚拟化就有意义了,考虑如下两个场景:

  1. 新闻客户端,数据来源是来自于远程的Rest服务,但是它的接口是分页获取的,只能每次获取50条,总共却可能有100页。
  2. 图片浏览器,图片不是来自于本地,而是来自于图片服务网站。

第一个例子就是比较典型的数据虚拟化的应用场景了,如果一开始就加载所有100页新闻就需要花费大量时间了。第二个例子则是部分数据虚拟化,图片信息无需虚拟化,但图片呈现需要虚拟化,只是在需要呈现的时候才从网络下载。

WPF的UI虚拟化的更多相关文章

  1. 【WPF】UI虚拟化之------自定义VirtualizingWrapPanel

    原文:[WPF]UI虚拟化之------自定义VirtualizingWrapPanel 前言 前几天QA报了一个关于OOM的bug,在排查的过程中发现,ListBox控件中被塞入了过多的Item,而 ...

  2. WPF listbox UI虚拟化

    ListBox  默认是UI虚拟化的. 1. 原生使用  <ListBox VirtualizingPanel.IsVirtualizing="True" Virtualiz ...

  3. WPF之UI虚拟化

    在WPF应用程序开发过程中,大数据量的数据展现通常都要考虑性能问题.有下面一种常见的情况:原始数据源数据量很大,但是某一时刻数据容器中的可见元素个数是有限的,剩余大多数元素都处于不可见状态,如果一次性 ...

  4. wpf 客户端【JDAgent桌面助手】开发详解(三) 瀑布流效果实现与UI虚拟化优化大数据显示

    目录区域: 业余开发的wpf 客户端终于完工了..晒晒截图 wpf 客户端[JDAgent桌面助手]开发详解-开篇 wpf 客户端[JDAgent桌面助手]详解(一)主窗口 圆形菜单... wpf 客 ...

  5. WPF多线程UI更新——两种方法

    WPF多线程UI更新——两种方法 前言 在WPF中,在使用多线程在后台进行计算限制的异步操作的时候,如果在后台线程中对UI进行了修改,则会出现一个错误:(调用线程无法访问此对象,因为另一个线程拥有该对 ...

  6. windowsphone 瀑布流&ui虚拟化

    瀑布流已经有点年代了吧,不过wp上还真是挺少资料的.今天抽空把自己之前搞过的东西写出来,避免大家重复劳动. 一.简单的瀑布流排版加入ui虚拟化. 最近看了 段博琼  ui虚拟化的一篇博文,链接:htt ...

  7. WPF Modern UI 主题更换原理

    WPF Modern UI 主题更换原理 一 . 如何更换主题? 二 . 代码分析 代码路径 : FirstFloor.ModernUI.App / Content / SettingsAppeara ...

  8. WPF 模拟UI 键盘录入

    原文:WPF 模拟UI 键盘录入 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/yangyisen0713/article/details/1835 ...

  9. (转)基于 WPF + Modern UI 的 公司OA小助手 开发总结

    原文地址:http://www.cnblogs.com/rainlam163/p/3365181.html 前言: 距离上一篇博客,整整一个月的时间了.人不能懒下来,必须有个阶段性的总结,算是对我这个 ...

随机推荐

  1. 安全测试===sqlmap(零)转载

    本文转自:https://blog.werner.wiki/sqlmap-study-notes-0/ 感谢作者的整理,如有侵权,立删 零.前言 这篇文章是我学习Sqlmap的用法时做的笔记,记录了S ...

  2. 使用cURL POST上传文件

    使用cURL POST上传文件 http://blog.csdn.net/v6543210/article/details/20152575

  3. sicily 1046. Plane Spotting

    1046. Plane Spotting Time Limit: 1sec    Memory Limit:32MB  Description Craig is fond of planes. Mak ...

  4. Leetcode 之Binary Tree Preorder Traversal(42)

    树的先序遍历.定义一个栈,先压入中间结点并访问,然后依次压入右.左结点并访问. vector<int> preorderTraversal(TreeNode *root) { vector ...

  5. recv函数的MSG_PEEK标志介绍

    考虑下面的场景,server向client发送数据"_META_DATA_\r\n_USER_DATA_",要求"\r\n"之前的数据_META_DATA_在第 ...

  6. LeetCode解题报告—— Unique Binary Search Trees & Binary Tree Level Order Traversal & Binary Tree Zigzag Level Order Traversal

    1. Unique Binary Search Trees Given n, how many structurally unique BST's (binary search trees) that ...

  7. [你必须知道的.NET]第二十七回:interface到底继承于object吗?

    发布日期:2009.03.05 作者:Anytao © 2009 Anytao.com ,Anytao原创作品,转贴请注明作者和出处. 说在,开篇之前 在.NET世界里,我们常常听到的一句话莫过于“S ...

  8. Javascript备忘录-枚举一个对象的所有属

    for...in 循环 var obj = { age: 18, fname: "Rand ", lname: "McKinnon" }; function s ...

  9. datetimepicker时间控件

    喜欢上datetimepicker源自于对bootstrap的喜欢. 一款简单到爆的时间空间 引入jq 引入bootstrap 引入datetimepicker和bootstrap-datetimep ...

  10. Python和xml简介

    python提供越来越多的技术来支持xml,本文旨在面向初学利用Python处理xml的读者,以教程的形式介绍一些基本的xml出来概念.前提是读者必须知道一些xml常用术语. 先决条件 本文所有的例子 ...