提供3000多款全球软件/控件产品
针对软件研发的各个阶段提供专业培训与技术咨询
根据客户需求提供定制化的软件开发服务
全球知名设计软件,显著提升设计质量
打造以经营为中心,实现生产过程透明化管理
帮助企业合理产能分配,提高资源利用率
快速打造数字化生产线,实现全流程追溯
生产过程精准追溯,满足企业合规要求
以六西格玛为理论基础,实现产品质量全数字化管理
通过大屏电子看板,实现车间透明化管理
对设备进行全生命周期管理,提高设备综合利用率
实现设备数据的实时采集与监控
利用数字化技术提升油气勘探的效率和成功率
钻井计划优化、实时监控和风险评估
提供业务洞察与决策支持实现数据驱动决策
原创|其它|编辑:郝浩|2009-04-27 09:32:31.000|阅读 725 次
概述:详谈WPF开发中的数据虚拟化
# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>
UI虚拟化
当一个WPF的ItemControl被绑定到一个大型集合的数据源时,如果可以UI虚拟化,该控件将只为那些在可以看到的项创见可视化的容器(加 上面和下面的少许)。这是一个完整集合中有代表性的一小部分。用户移动滚动条时,将为那些滚动到可视区域的项创建新的可视化容器,那些不再可见的项的容器 将被销毁。当容器设置为循环使用时,它将再使用可视化容器代替不断的创建和销毁可视化容器,避免对象的实例化和垃圾回收器的过度工作。
数据虚拟化
数据虚拟化是指绑定到ItemControl的真实的数据对象的归档虚拟化的时间段。数据虚拟化不是由WPF提供的。作为对比,基本数据对象的小集 合对内存的消耗不是很多;但是,大集合的内存消耗是非常严重的。另外,真实的检索数据(例如,从数据库)和实例化数据对象是很耗时的,尤其当是网络数据调 用时。因此,我们希望使用数据虚拟化机制来限制检索的数据的数量和在内存中生成数据对象的数量。
解决方案
总览
这个解决方案是只在ItemControl绑定到IList接口的实现时起作用,而不是IEumerable的实现,它并不枚举整个列表,而只是读 取需要显示的项。它使用Count属性判断集合的大小,推测并设置滚动的范围。然后使用列表索引重新确定要在屏幕上显示的项。因此,创建一个可以报告具有 大量项的,并且可以只检索需要的项的IList。
IItemsProvider
///The start index. /// The number of items to fetch. /// IList } |
如果下面的查询是一个数据库查询,它是一个利用大多数据库供应商都提供的COUNT()聚集函数和OFFSET与LIMIT表达式的一个IItemProvider接口的一个简单实现。
VirtualizingCollection
下面讨论我们有兴趣的部分。详细信息请参考附件中的源代码项目。
IList实现的第一个方面是实现Count属性。它通常被ItemsControl用来确定集合的大小,并呈现适当的滚动条。
private int _count = -1; public virtual int Count { get { if (_count == -1) { LoadCount(); } return _count; } protected set { _count = value; } } protected virtual void LoadCount() { Count = FetchCount(); } protected int FetchCount() { return ItemsProvider.FetchCount(); } |
Count属性使用延迟和懒惰加载(lazy loading)模式。它使用特殊值-1作为未加载的标识。当第一次读取它时,它从ItemsProvider加载其实际的数量。
IList接口的实现的另一个重要方面是索引的实现。
private int _count = -1;
public virtual int Count
{
get
{
if (_count == -1)
{
LoadCount();
}
return _count;
}
protected set
{
_count = value;
}
}
protected virtual void LoadCount()
{
Count = FetchCount();
}
protected int FetchCount()
{
return ItemsProvider.FetchCount();
}
这个索引是这个解决方案的一个聪明的操作。首先,它必须确定请求的项在哪个页(pageIndex)中,在页中的位置(pageOffset),然后调用RequestPage()方法请求该页。
附加的步骤是然后根据pageOffset加载后一页或前一页。这基于一个假设,如果用户正在浏览第0页,那么他们有很高的机率接下来要滚动浏览第1页。提前把数据取来,就可以无延迟的显示。
然后调用CleanUpPages()清除(或卸载)所有不再使用的页。
最后,放置页不可用的一个防御性的检查, 当RequestPage没有同步操作时是必要的,例如在子类AsyncVirtualizingCollection
// ... |
页存储在以页索引为键的字典(Dictionary)中。一个附加的字典(Dictionary)记录着每个页的最后存取时间,它用于在CleanUpPages()方法中移除较长时间没有存取的页。
protected virtual void LoadPage(int pageIndex) |
为完成该解决方案,FetchPage()执行从ItemProvider中抓取数据,LoadPage()方法完成调用PopulatePage方法获取页并把该页存储到字典(Dictionary)中的工作。
看起来好象有一些太多的不全逻辑的方法(a few too many inconsequential methods),但这样设计是有原因的:每一个方法做且只做一件事,有助于提高代码的可读性,并使在子类中进行功能扩展和维护变得容易,下面可以看到。
类VirtualizingCollection
AsyncVirtualizingCollection
WPF中异步数据源的关键是在数据抓取完成后必须通知UI的数据绑定。在规则的对象中,是通过实现INotifyPropertyChanged接 口实现的。对一个集合的实现,需要紧密的关系,INotifyCollectionChanged。那是ObservableCollection
public event NotifyCollectionChangedEventHandler CollectionChanged; |
实现了INotifyCollectionChanged接口和INotifyPropertyChanged接口。提供数据绑定弹性最大化。这个实现没有任何要注意的。
protected override void LoadCount() |
在重载的LoadCount()方法中,抓取是由ThreadPool(线程池)异步调用的。一旦完成,就会重置Count,UI的更新是由 INotifyCollectionChanged接口调用FireCollectionReset方法实现的。注意 LoadCountCompleted方法会在UI线程通过SynchronizationContext再一次被调用。假定集合的实例在UI线程中被创 建,SynchronationContext属性就会被设置。
protected override void LoadPage(int index){IsLoading = true; ThreadPool.QueueUserWorkItem(LoadPageWork, index);} private void LoadPageWork(object args){ int pageIndex = (int)args; IList SynchronizationContext.Send(LoadPageCompleted, new object[]{pageIndex, page});} private void LoadPageCompleted(object args){int pageIndex=(int)((object[]) args)[0]; IList IsLoading = false; FireCollectionReset();} |
页数据的加载遵循相同的惯例,再一次调用FireCollectionReset方法更新用户UI。
也要注意IsLoading属性是一个简单的标识,可以用来告知UI集合正在加载。当IsLoading改变后,由INotifyPropertyChanged机制调用FirePropertyChanged方法更新UI。
public bool IsLoading{ get{ return _isLoading; } set {if ( value != _isLoading ){ _isLoading = value; FirePropertyChanged("IsLoading");} }} |
演示项目
为了演示这个解决方案,我创建了一个简单的示例项目(包括附加的源代码项目)。
首先,创建一个IItemsProvider的一个实现,它通过使用线程休眠来模拟网络或磁盘行为的延迟提供虚拟数据。
public class DemoCustomerProvider : IItemsProvider
{
private readonly int _count;
private readonly int _fetchDelay;
public DemoCustomerProvider(int count, int fetchDelay)
{
_count = count;
_fetchDelay = fetchDelay;
}
public int FetchCount()
{
Thread.Sleep(_fetchDelay);
return _count;
}
public IListFetchRange(int startIndex, int count)
{
Thread.Sleep(_fetchDelay);
Listlist = new List ();
for( int i=startIndex; i
普遍存在的Customer(消费者)对象作为集合中的项。
为了允许用户试验不同的列表实现,创建一个包含ListView的简单WPF窗体。
xmlns="//schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="//schemas.microsoft.com/winfx/2006/xaml"
Title="Data Virtualization Demo - By Paul McClean" Height="600" Width="600">
TextAlignment="Right" VerticalAlignment="Center"/>
Text="1000000" Width="60" VerticalAlignment="Center"/>
TextAlignment="Right" VerticalAlignment="Center"/>
Text="1000" Width="60" VerticalAlignment="Center"/>
TextAlignment="Right" VerticalAlignment="Center"/>
Margin="5" Content="List(T)" VerticalAlignment="Center"/>
Margin="5" Content="VirtualizingList(T)"
VerticalAlignment="Center"/>
Margin="5" Content="AsyncVirtualizingList(T)"
IsChecked="True" VerticalAlignment="Center"/>
TextAlignment="Right" VerticalAlignment="Center"/>
Text="100" Width="60" VerticalAlignment="Center"/>
TextAlignment="Right" VerticalAlignment="Center"/>
Text="30" Width="60" VerticalAlignment="Center"/>
VerticalAlignment="Center"/>
Width="80" VerticalAlignment="Center"/>
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@pclwef.cn
文章转载自:自互联网面对“数字中国”建设和中国制造2025战略实施的机遇期,中车信息公司紧跟时代的步伐,以“集约化、专业化、标准化、精益化、一体化、平台化”为工作目标,大力推进信息服务、工业软件等核心产品及业务的发展。在慧都3D解决方案的实施下,清软英泰建成了多模型来源的综合轻量化显示平台、实现文件不失真的百倍压缩比、针对模型中的大模型文件,在展示平台上进行流畅展示,提升工作效率,优化了使用体验。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
本站的模型资源均免费下载,登录后即可下载。模型仅供学习交流,勿做商业用途。
服务电话
重庆/ 023-68661681
华东/ 13452821722
华南/ 18100878085
华北/ 17347785263
客户支持
技术支持咨询服务
服务热线:400-700-1020
邮箱:sales@pclwef.cn
关注我们
地址 : 重庆市九龙坡区火炬大道69号6幢