WPF平台Grid控件性能比较
WPF官方发布第一个版本至今已经有10年了, 我们几乎在同时也开始了XAML开发。即使经过多年打造,我们依旧尝试提高:我们真的成功打造了高效灵活的控件吗?我没有在其他地方找到任何关于优秀的WPF表格性能比较的介绍,只有少量而年代久远的现在已经不存在的控件的讨论。这个新基准是一种尝试,用来在一些市场相对流行的控件比较中发现我们的优势和不足。
环境
这个基准创建于2016年6月,使用了下面Grid控件。(我们使用的最新试用版)
- System.Windows.Controls 下的DataGrid (PresentationFramework.dll的一部分)
- C1FlexGrid 4.4.0.20162.514 (ComponentOne WPF版)
- C1DataGrid 4.4.0.20162.514 (ComponentOne WPF版)
- XamDataGrid v16.1.16.1.20161.1000 (WPF Controls - Infragistics)
- GridControl v15.2.15.2.10.0 (WPF Controls | DevExpress)
- SfDataGrid 14.1400.0.41 (Syncfusion Essential Studio WPF版 )
- RadGridView 2016.2.503.40 (Telerik WPF Controls | UI WPF版)
- DataGridControl v5.9.5.9.16204.15420 (Xceed DataGrid for WPF)
这个基准运行于ENVY-23 All-in-One Desktop环境,拥有下面的配置。
Intel i7 quad-core CPU @ 3.10 GHz
8 GB RAM
NVIDIA GeForce GT 630M display adapter, Full HD (1920 x 1080) resolution
Windows 10 Pro 64-bit OS
所有的Grid控件设置为相同的尺寸和默认的外观 。
测试应用
我们的基准应用程序允许选择和运行单独的测试或者允许一个接一个运行所有的测试。您可以选择同一个测试运行的次数,这样可以在结果中得到平均值。
我们这样做可以减少其他方面的影响,比如操作系统和其他应用程序的交互。所有展示在这里的结果都会运行10次。下面是应用程序窗口。
![]()
基准测试应用程序窗口
如果要分析一个指定的用例,运行一个单独的测试是非常方便的。注意:您需要在不同的测试间比较,在测试运行时请不要改变窗体的尺寸。实际的视图尺寸会影响性能,就像大屏幕会消耗更多时间和虚拟控件等资源用来布局从而影响其他事件。
这个应用会将测试结果写进working文件夹下的Excel文件。如果您需要一个更详细的日志文件,您可以在App.xmal.cs文件中去掉输出到TraceListener的注释。
这里最有趣的地方就是,如何去测试异步UI更新时的复杂操作的运行时间。在几次试验后,我们发现我们想到的就是最合适的方法,用于去获取当Girder UI完成更新时的准确时刻。完整源代码已经附加,您可以去尝试。我们将很高兴收到关于您认为我们可以在某些方面可以提高的反馈。
我们这里不包含任何的控件的二进制版本。如果您想运行应用,您需要下载我们的WPF版本的试用版和其他参与比较的控件的使用版。它们都拥有30天的免费试用期,这将不是问题。
基准
我们选择ListCollectionView作为数据源并且用下面定义的业务对象来填充它。
public class Customer : INotifyPropertyChanged, IEditableObject
{
public int ID { get; set;}
public string Name { get;}
public string Country { get;}
public int CountryID { get; set;}
public bool Active { get; set;}
public string First { get; set;}
public string Last { get; set;}
public DateTime Hired { get; set;}
public double Weight { get; set;}
public string Father { get;}
public string Brother { get;}
public string Cousin { get;}
}
它提供了12个不同类型的列。
我们尝试为Grid设置相同的条件,对于某些控件,我们更改了某些设置来达到这一要求。
- 自动生成列
- 固定列宽
- 允许在底部新行位置添加新行
- 隐藏分组和搜素面板
- 可编辑的单元格
每一个基准要遵循下面的步骤
1. 移除上一次测试所创建的所有UI。 调用GC.Collect 和GC.WaitForPendingFinalizers方法,使垃圾回收不会影响下次测试;
2. 初始化下次测试和 Stopwatch计时器;
3. 按照需要的次数执行测试;
4. 测量总时间并计算平均结果;
5. 记录结果。
下面解释关于指定基准的实现细节
基准1 创建控件并加载数据。
这个基准创建了一个用户控件,包含一个用于测试的Grid。 将它插入到可视化树中并填充数据。 这样唯一的麻烦就是用代码创建的Xceed DataGridControl并不能正常工作。因此您将看到附加的应用使用XAML创建它。
基准2: 重新加载数据到存在的控件
基准设置DataGrid的ItemsSource为null,用于清空数据和自动生成的列。然后设置ItemsSource 为一个新的ListCollectionView。在代码里,它就像下面这样(对于所有测试的控件都一样)
public override void Load(IList data)
{
if (data == null)
{
_grid.ItemsSource = null;
}
else
{
_grid.ItemsSource = new ListCollectionView(data);
}
}
基准3: 排列单列
我们尝试减少测试中自定义的代码,因此大多数情况下我们通过IcollectionView接口来实现排列。
public override void Sort(bool ascending)
{
ICollectionView dataView = CollectionViewSource.GetDefaultView(_grid.ItemsSource);
dataView.SortDescriptions.Clear();
dataView.SortDescriptions.Add(new SortDescription("ID", ascending ?
ListSortDirection.Ascending : ListSortDirection.Descending));
}
这是非常标准的,并且我们希望每个Grid都应内置支持。但是Syncfusion的 SfDataGrid 并没有支持,所以我们需要通过SfDataGrid.SortDescriptions属性来实现排序。
我们测试Infragistics的XamDataGrid时遇到了一个麻烦,他可以使用ICollectionView 排序,但是遇到大数据时变得很慢。当我们想要得到所有控件的对比结果时,我们最终通过FieldLayout.SortedFields来实现它。
基准4和5,滚动100行,滚动整个表单。
我们认为这在测试中可以很好的模拟最终用户交互,但是没有找到一个很好的办法。我们也许可以通过在可视化树中找到滚动条并滚动。但是相关的代码也会影响性能,因此我们决定坚持使特定行进入视图。所有的Grid都拥有ScrollIntoView或者相似的办法来解决这件事。
测试结果
初始化加载时间
为了在所有的测试中避免计算JIT编译和XAML解析的次数,我们从每个控件的一个单独的测试开始整个基准,这跟基准1是几乎是相同的。 当您在整个应用程序生命周期中第一次运行它,您可以发现它跟接下来的运行不同 。 它被测量作为应用程序的启动时间,这对WPF很关键,下面的测试显示了不论数据规格几乎相同的结果。

初始化加载时间
固定宽度基准
下面是1,000,10,000,和100,000项作为数据源的结果

固定列宽下1000 行数据的结果

固定列宽下10,000行数据的结果

固定列宽下100,000行数据的结果
自动列宽基准
在运行了固定列宽的测试之后,我们决定比较一下他们在自动列宽时的表现。我们这项测试只针对四种具有即时自动列宽的Grid。我想在每个Grid的最好情况下得到比较结果,因此我们选择MS的DataGrid 和Telerik的 RadGridView的默认SizeToHeader选项,C1DataGrid的 默认AutoStar选项和Infragistics的XamDataGrid.的默认FieldLength.InitialAuto选项。
为什么我们不对所有的控件都做这项测试呢?我们的C1FlexGrid和DevExpress的GridControl以及Xceed的DataGridControl不支持即时列宽计算。显然,这是设计者为了集中于控件的性能而做出的牺牲。上面的所有控件都支持调用方法来自动计算列宽,但您需要在合适的时间来调用合适的方法。这使它很难衡量整体性能,您也不能确定测试结果是完全依赖于性能的。所以在我们的比较中不包含那些控件。
反之,Syncfusion 的SfDataGrid 控件没有类似MS DataGrid 和其他控件的自动列宽计算的选项,但是由于适用的选项在加载大数据时速度变得很慢,它和其他控件是没法相比的。所以在这个测试中我们也排出了它。下面是我们分别测试包含1,000, 10,000和100,000条数据的数据源得到的结果。(与固定列宽用的是同样的基准)

自动宽度下1000行数据的结果。

自动宽度下10,000 行数据的结果。

自动宽度下100,000 行数据的结果。
一些条件
我们的结果与很久之前的关于WPF Grid性能的讨论不同,显然现在的控件都具有可视化能力并且可以处理大量数据,如果您打算为您的应用程序选择一个Grid,我们的结果是一个很好的参考。
另外没注意我们没有测试其他的场景,比如,分组、过滤和列数据可视化。还有,性能并不代表全部,您有可能因为一些其它的原因而喜欢上某个控件。比如易用性,XAML定制能力,内嵌支持的特性数量等。
在制定这些基准的时候,我阅读了很多关于控件比较的信息,给我很深的印象就是所有的WPFGrid可以分为下面两类:
- 基于性能的Grid,不包含在自动列宽计算的测试中
- 集中于易用性和XAML运用。
我们的WPF版本中包含以上两种控件,所以您可以选择最适应您需要的一种。更多信息,参考附件中关于C1FlexGrid, C1DataGrid 和MS DataGrid详细功能的比较。
最终,在整个基准的比较的过程中,我情不自禁地要概括我们自己的控件。所以我们又得到一个很有用的信息:2016 v2版本的C1DataGrid控件的速度优于之前的发布版本35%以上。
- 下载WPFGridsBenchmark源代码 (19 KB zip)
- 下载1000行数据测试结果 (38.5 KB xls)
- 下载10,000行数据测试结果 (38.5 KB xls)
- 下载100,000行数据测试结果(38.5 KB xls)
- 下载C1FlexGrid, C1DataGrid 和MS DataGrid 特性比较表(17.7KB xlsx)
WPF平台Grid控件性能比较的更多相关文章
- 实现控件WPF(4)----Grid控件实现六方格
PS:今天上午,非常郁闷,有很多简单基础的问题搞得我有些迷茫,哎,代码几天不写就忘.目前又不当COO,还是得用心记代码哦! 利用Grid控件能很轻松帮助我们实现各种布局.上面就是一个通过Grid单元格 ...
- wpf研究之道-grid控件
想要说些什么,却不知道从哪开始."形而上谓之道,形而下谓之器".与其坐而论道,不如脚踏实地,从最实用的地方开始. 我们先来看看wpf中的grid控件.grid控件是个网格的布局控件 ...
- Windows Community Toolkit 3.0 新功能 在WinForms 和 WPF 使用 UWP 控件
本文告诉大家一个令人震惊的消息,Windows Community Toolkit 有一个大更新,现在的版本是 3.0 .最大的提升就是 WinForm 和 WPF 程序可以使用部分 UWP 控件. ...
- WPF中Ribbon控件的使用
这篇博客将分享如何在WPF程序中使用Ribbon控件.Ribbon可以很大的提高软件的便捷性. 上面截图使Outlook 2010的界面,在Home标签页中,将所属的Menu都平铺的布局,非常容易的可 ...
- WPF 在image控件用鼠标拖拽出矩形
原文:WPF 在image控件用鼠标拖拽出矩形 版权声明:博客已迁移到 http://lindexi.gitee.io 欢迎访问.如果当前博客图片看不到,请到 http://lindexi.gitee ...
- 示例:WPF中Slider控件封装的缓冲播放进度条控件
原文:示例:WPF中Slider控件封装的缓冲播放进度条控件 一.目的:模仿播放器播放进度条,支持缓冲任务功能 二.进度: 实现类似播放器中带缓存的播放样式(播放区域.缓冲区域.全部区域等样式) 实现 ...
- 扩展ToolBarManager、ListView和Grid控件以实现气球式的ToolTip
原文:扩展ToolBarManager.ListView和Grid控件以实现气球式的ToolTip infragistics是全球领先的UI工具和用户体验的专家,Infragistics开发了一系列的 ...
- 浅尝辄止WPF自定义用户控件(实现颜色调制器)
主要利用用户控件实现一个自定义的颜色调制控件,实现一个小小的功能,具体实现界面如下. 首先自己新建一个wpf的用户控件类,我就放在我的wpf项目的一个文件夹下面,因为是一个很小的东西,所以就没有用mv ...
- 深入探讨WPF的ListView控件
接上一篇博客初步探讨WPF的ListView控件(涉及模板.查找子控件) 我们继续探讨ListView的用法 一.实现排序功能 需求是这样的:假如我们把学生的分数放入ListView,当我 ...
随机推荐
- iconfont的蜕化操作
很多国外的网站,访问的时候可以看到,页面先是大面积白一下,然后恢复正常.原因是网页上用到了 webfont,这些页面很多情况都是直接引用 google 的 webfont 地址,中华大局域网下,由于网 ...
- Unit Testing with NSubstitute
These are the contents of my training session about unit testing, and also have some introductions a ...
- 关于Unicode,字符集,字符编码,每个程序员都应该知道的事
关于Unicode,字符集,字符编码,每个程序员都应该知道的事 作者:Jack47 李笑来的文章如何判断一个人是否聪明?中提到: 必要.清晰.且准确的概念,是一切思考的基石.所谓思考,很大程度上,就是 ...
- 修改HTML5 input placeholder 颜色及修改失效的解决办法
input::input-placeholder{color: #bdbdbd ;} /* 有些资料显示需要写,有些显示不需要,但是在编辑器webstorm中该属性不被识别 */ ::-webkit- ...
- SSIS Design7:数据类型的选择
对于SSIS的数据类型,容易遗漏精度的是DateTime,不正确的使用DateTime,time,decimal 等数据类型,可能导致溢出或数据丢失. 1,Variable 和 Parameter的D ...
- 虚拟机网络驱动(共享文件夹)不见了的解决方案-适用于win7~win10 and Windows Server 2008~Windows Server 2012R2
具体看图 手动打入下面选择部分的字符 \\vmware-host\Shared Folders 然后就可以了,这边有个红叉,重启后就没了 重启后
- 专业上的常用的工具和类库集 By 老衣
Visual Studio 2013 扩展 CodeMaid: 可快速整理代码文件,清理不必要的代码和杂乱的格式.并在开发时实时提供代码复杂度的报告,以便帮助开发人员降低代码复杂度.提高代码质量. C ...
- LINQ系列:Linq to Object生成操作符
生成操作符从现有序列值中创建新的序列. 1. Empty Empty操作符返回一个指定类型的空集. 1>. 原型定义 public static IEnumerable<TResult& ...
- JAVA的静态变量、静态方法、静态类
静态变量和静态方法都属于静态对象,它与非静态对象的差别需要做个说明. (1)Java静态对象和非静态对象有什么区别? 比对如下: 静态对象 ...
- iOS开发之地图与定位
无论是QQ还是微信的移动客户端都少不了定位功能,之前在微信demo中没有添加定位功能,今天就写个定位的小demo来了解一下定位和地图的东西.地图和定位看上去是挺高大上一东西,其实用法比TableVie ...