wpf设计wpf报表控件应该怎么弄

帮助企业打造成功软件!
热门搜索:
4款主流的WPF报表控件推荐
4款主流的WPF报表控件推荐
| 作者: |
10:06:12| 阅读 0次
概述:根据统计,目前市面上使用最为广泛的WPF报表控件有4款,分别为ActiveReports,SharpShooter Reports.WPF,Stimulsoft Reports.Wpf和XtraReports Suite,这四款报表控件各有异同,本文就这4款WPF报表控件进行分析,帮助你选择最合适自己的报表控件
多年来ActiveReports已经提供了 Windows Forms、Web、Silverlight和Flash平台的报表查看器控件,然而,伴随着ActiveReports 7 SP1 的发布,它提供了WPF平台的专业报表查看器控件WPFViewer,用户可以在WPF 平台使用ActiveReports产品。
推荐理由:
用户群多,中文资源丰富
操作简便、采用拖拽式操作,不会编程也可以进行报表设计
多种报表模型,满足交互式报表等复杂报表需求
零版税快捷部署,降低成本和IT负担
金牌服务专业版¥15,500(日前购买每套赠送一套金牌服务专业版)
SharpShooter Reports.WPF是原生的基于XAML的WPF报表控件,稳定性好、功能强大,用户只需简单的点击数次鼠标即可从多数据源创建相当复杂的报表,并将之发送至Windows Presentation Foundation。SharpShooter Reports.WPF支持多种数据源,能够快速,轻松地集成到现有系统中。
推荐理由:
稳定性好、功能强大,而且支持多种数据源
终端用户设计器可帮助用户对最终报表和报表模板进行修改
专业版¥19950
针对wpf用户界面架构开发的报表工具,无需上网,即能轻松实现控件所有功能,包括界面更换、查看、打印、导出等功能。
报表功能非常丰富,适合创建复杂报表
产品部署无服务器许可证费用,无客户端费用,只要购买开发者许可证即可
界面漂亮,并内置多款皮肤,符合现代应用的开发的需求
报表导出格式全,打印灵活,所见即所得
&专业版¥17900
XtraReports Suite是属于DXperience控件包中的一个报表控件,功能很全面,而且官方支持WinForms, ASP.NET, MVC, WPF, Silverlight和LightSwitch这6种开发环境。XtraReports得益于Devexpress公司.Net控件的优秀架构,扩展非常灵活,它不但自身已经包含了很多报表元件,比如:图表,交叉表,条形码和表格,而且还能将第三方的.NET控件作为报表原件使用。
用户群广,中文资源非常丰富
界面炫丽,支持多种皮肤
支持各种报表类型,另外可以一次做模板,多平台发布
本站文章除注明转载外,均为本站原创或翻译
欢迎任何形式的转载,但请务必注明出处,尊重他人劳动成果
转载请注明:文章转载自:慧都控件网 []
本文地址:WPF中怎么做一个可以自动增加的表格啊??
[问题点数:100分]
WPF中怎么做一个可以自动增加的表格啊??
[问题点数:100分]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
相关帖子推荐:
2006年4月 总版技术专家分月排行榜第一
2006年3月 总版技术专家分月排行榜第三
2006年4月 总版技术专家分月排行榜第一
2006年3月 总版技术专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。请问如何在c#的wpf做一个rdlc报表,数据库是sqlite 但是需要绑定两个数据库的table 请问这个怎么去做呢?_百度知道
请问如何在c#的wpf做一个rdlc报表,数据库是sqlite 但是需要绑定两个数据库的table 请问这个怎么去做呢?
拜托各位了
分数什么的都好说
作为初始表建立REPORT,连接表可以来自两个或者N个远程数据库,分析好表的关系,用代码填充新的DataSet,ACCESS在组合数据表上绝对优越与C#机制借助ACCESS作为工具,在ACCESS中建立查询,Report向导需要一个数据源,SQL也好Ocxle也好Excle也一样可以作为ACCESS的网络连接表,而且你可以设置他一个密码,这样你既给报表做了初始化,也给报表提高了查询分析效率.在C#中直接连接ACCESS的查询表,再用ACCESS做连接表,用ACCESS建立空表,把新的DataSet去取代Report初始状态的Dataset
其他类似问题
按默认排序
其他1条回答
2思路如下.先把两个数据库中的table取出来。具体方法你查一下百度:1。放到一个dataset中.把数据推送到rdlc表的数据引擎中
sqlite的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁在wpf中怎样确定窗体的标题栏的高度?该如何解决 - .NET新技术栏目()
在wpf中怎样确定窗体的标题栏的高度?该如何解决
&&&整理于: 23:39&&&阅读:次
如题.xaml里的windows标签的height是整个窗体的高度,包括标题栏.而标题栏的高度不知道,对于界面的设计是一个障碍.请问,怎样知道标题栏的高度,或者设计界面的时候不考虑标题栏?-----参考解决方法-------SystemParameters.CaptionHeight
-----参考解决方法-------WPF可以不用考虑边框 标题栏大小,你只需要关注Window.Content的实际大小就可以 也就是Window的内容实际大小 ActualHeight 和 ActualWidth
-----参考解决方法-------SystemParameters.CaptionHeight
-----参考解决方法-------探讨WPF可以不用考虑边框 标题栏大小,你只需要关注Window.Content的实际大小就可以 也就是Window的内容实际大小 ActualHeight 和 ActualWidth
开发者笔记
软件开发/管理/测试
企业管理/开发
嵌入式开发
高性能开发
编程语言/框架
专题项目/开发/技术
Linux/Unix&&& 最近用
做的仓库管理系统中,许多界面的都需要使用表格控件来显示数据。一是这些表格的列非常多,有的甚至达到了 200 列,而且一个模块的界面中可能同时显示好几个表格。这导致界面的速度比较慢,特别是较多数据需要展现时。经检测,表现虽然表格的行已经做了虚拟化,但是由于列非常多,最终还是造成可视树中的元素过多,而导致界面布局代码运行过慢。假设只有 30 行,一个单元格仅生成 5 个可视元素,200 列的单元格都会产生 3W 个可视元素,而布局系统的 Measure 方法需要对可视树中的每一个元素都调用其对应的 Measure 方法,可以想象,这当然会很慢。
&&& 那么,要解决上述的问题,只有同时实现表格的行、列虚拟化,才能有效地减少表格的可视元素,从而提高系统性能。还好,OEA 中的 TreeGrid 本身就是我们自己为 OEA 量身定制的控件,所以可以直接改造。
&&& 但是,要同时在一个表格控件中同时实现行、列虚拟化呢?我们得先看看如何在 WPF 中实现虚拟化。
WPF 虚拟化相关知识
&&& 我之前写过一篇文章《》,里面引用了许多老外的文章,说明了要实现界面虚拟化需要做的几件事。这里我来汇总下:
* 设置 ScrollViewer.CanContentScroll 为 True。默认为 False 时,ScollViewer 自己实现了滚动逻辑,在 Measure 时会把 Infinite 传给 Content 元素;而当该值被设置为 True时,ScrollViwer 认为它的 Content 元素自己实现了 IScrollInfo 并处理所有的滚动逻辑。
* 从 VirtualizingPanel 继承出一个子类,并让这个新的 Panel(以下称为 UIVPanel) 实现 IScrollInfo。
* 在 UIVPanel 中实现虚拟化逻辑,生成或销毁界面元素。
&&& 1. 要知道如何实现 IScrollInfo,则需要明白 IScrollInfo 的设计原理:
&&& 如果 UIVPanel 元素自己要处理滚动信息,它必须知道当前滚动条的 OffSet,并告知 ScrollViewer 需要的总大小是多少,这样才能正确地显示滚动条。由于 UIVPanel 元素的 Measure 方法被 ScrollViwer 调用时,参数只能传入和传出视窗的大小,那么,外围的 ScrollViewer 想要和 UIVPanel 交互更多的数据,例如传入 OffSet(VerticalOffSet 及 HorizontalOffSet)、获取 Extent(Height/Width),则只能通过 UIVPanel 本身的公有属性来交互,也就要求 UIVPanel 必须实现 IScrollInfo 中定义的所有属性及方法。(注意,IScrollInfo 中的所有方法,本质上只是期望设置新的 Offset,只是滚动的粒度不同而已。)
&&& 2. 实现 IScrollInfo 的 UIVPanel 与 ScrollViewer 交互的细节如下:
* ScollViewer 会在滚动条变更时,调用 UIVPanel 的 SetVerticalOffset 或者相关方法来变更 Offset 值,UIVPanel 则在 SetVerticalOffset 中调用 InvalidateMeasure 来重新测量自身。
* UIVPanel 的 MeasureOverride 方法中,参数是 ScrollViewer 传入的视窗大小,再获取其内部数据 VerticalOffset,最终计算出 IScrollInfo 中的 ExtentHeight/ExtentWidth(总高度/总宽度)。如果这个值有所变化,则应该调用 ScrollOwner.InvalidateScrollInfo 通知 ScrollOwner 来重新获取最新的总高度,以计算出滚动条最新的大小。
&&& 在与 ScrollViewer 交互完成的同时,UIVPanel 还应该根据提供的视窗大小,调用基类 VirtualizingPanel 中 ItemContainerGenerator 属性的一套元素生成方法,通过视窗大小、当前 Offset,来生成新的需要显示的容器,并移除不可见的容器,最终达到虚拟化的效果。
&&& 3. GeneratorPosition 类的含义:
&&& (不知道 GeneratorPosition 类型的朋友,可以先看一下这篇文章中的《》代码。)
&&& 在使用 ItemContainerGenerator 来生成元素时,需要理解 GeneratorPosition 的含义。它中有两个属性:Index 及 Offset,它们的意义可以从 IndexFromGeneratorPosition 方法中理解出来:
&&& Index 如果大于等于 0 时,则表示一个生成好的项容器在所有已经生成好的项容器中的索引。假设这个容器为 A,那么,在 A 的基础上,如果 Offset 是 0,则整个 GeneratorPosition 就表示项容器 A;而如果 Offset 非 0,则表示一个还没有生成的项容器 B,它距离 A 的相对位置正好是 Offset。
&&& Index 若是 -1 时,OffSet 如果是正数表示目标容器到起点的偏移量,如果是负数则表示目标容器到终点的偏移量。
&&& GeneratorPosition 类型的设计比较晦涩,不易理解。这跟 VirtualizingPanel.ItemContainerGenerator 中虚拟化的内部实现的数据结构是有关系的。虚拟化会把整个列表分割成多个小块,这些小块主要是两类:UnrealizedItemBlock(未实例化块)、RealizedItemBlock(已实例化块)。整个列表由这些块组合起来表示,假设一页能显示 30 条数据,则一个一万行的列表可能由以下小块组成:RealizedItemBlock 60,UnrealizedItemBlock 8000,RealizedItemBlock 150,UnrealizedItemBlock 1790,总和是一万。所有的块在 ItemContainerGenerator 中由一个双向链表存储在字段 _itemMap 中。_itemMap.Next 就是第一个块,也可以理解为起点或者终点。 UnrealizedItemBlock 与 RealizedItemBlock 类都继承自 ItemBlock。ItemBlock 中有两个重要属性:ItemCount、ContainerCount。ItemCount 表示本块代表了多少条数据,二者实现一致。而 ContainerCount 表示已经生成的容器的个数,对于 UnrealizedItemBlock 来说,永远返回 0; 而 RealizedItemBlock 返回它的 ItemCount 表示容器数就是项数。
&&& 所以,到现在已经能够看出,其实 GeneratorPosition 存储了某个 ItemBlock 的索引号,以及具体容器相对这个 ItemBlock 的偏移量。而操作 ItemContainerGenerator 都使用 GeneratorPosition,可以方便地和内部的数据结构交互。(这样设计的原因可能是出于性能的考虑?)
&&& 说完了 UIV 的相关知识,接下来,那我们就开始设计 TreeGrid 表格的虚拟化。
表格的虚拟化
&&& 由前面的内容可以看出,如果要在 WPF 中实现一个行列都支持虚拟化的 UIVPanel,只需要从 VirtualizingPanel 上继承下一个 UIVPanel 类型,并根据列的宽度来计算并生成相应的单元格就行了。但是如果这样设计的话,将会导致所有的单元格,都必须放在 UIVPanel 中。也就是说,TreeGrid 作为一个 ItemsControl,其中的所有单元格 TreeGridCell 都必须作为它的逻辑子容器。这样的设计虽然实现了界面虚拟化,但是并不可取。这是因为,开发人员对于 TreeGrid 的常见用法应该是:TreeGrid 中的每一项是一个表格行 TreeGridRow,而 TreeGridRow 又是一个 ItemsControl,行中其中的每一项才是横向排列的单元格 TreeGridCell。这样的场景导致 TreeGrid 的接口设计也应该是 TreeGrid -& TreeGridRow -& TreeGridCell 这样层级的接口,逻辑树、可视树也都应该是按这样的层次构建,易于使用、易于调试。
&&& 那么,在这样层次要求下,要如何实现只使用一个滚动条的虚拟化呢?还好,WPF 自带的 DataGrid 也带有行列虚拟化的功能,我们可以先看一下 DataGrid 是如何实现的。 下图是 DataGrid 打开行、列虚拟化功能后生成的可视树:
&&& 图1 DataGrid 虚拟化可视树结构
&&& 结合上面这个图,再查阅 DataGrid 源码,可以看出:
&&& * 整个 DataGrid 表格中只有一个 ScrollViewer,表格作为一个 ItemsControl,内部每一项是一个 DataGridRow,其内部作为 ItemsHost 使用的面板是 DataGridRowsPresenter 类型。DataGridRowsPresenter 继承自 VirtualizingStackPanel,就间接继承 VirtualizingPanel 并实现 IScrollInfo 接口,为最外层的 ScrollViewer 提供滚动信息,提供 DataGridRow 行的虚拟化功能。
&&& * 每一个 DataGridRow 中,使用一个继承自 ItemsControl 的 DataGridCellsPresenter 来生成每一个单元格的容器,而它则使用 DataGridCellsPanel 来作为 ItemsHost 面板。DataGridCellsPanel 也是一个继承自 VirtualizingPanel 的虚拟化面板。但是,它并没有实现 IScrollInfo。为了使用最外层 ScrollViewer 中的滚动条信息,它通过可视树往上查找到 DataGridRowsPresenter 来获取水平方向上的滚动条位置 HorizontalOffset,而通过这个值,来计算水平方向上需要显示的单元格,以实现虚拟化。
&&& * 另外,需要额外说明下两个 ItemsControl 的数据源:DataGrid 的 ItemsSource 当然就是应用层指定的数据模型的列表,这样,每一个 DataGridRow 的 DataContext 就是其中的一个数据模型对象。而有意思的是,表格行内的 DataGridCellsPresenter,作为一个横向显示单元格的控件,它也是一个 ItemsControl,也需要设置它的 ItemsSource 数据源属性。由于每一个行的 DataContext,也应该是每一个单元格的 DataContext,所以 DataGridCellsPresenter.ItemsSource 应该被设置为一个数据模型对象列表,其中每一个元素都是 DataGridRow.DataContext 对象,列表的长度就是表格列的个数,这样就可以生成和列的个数一致的单元格个数。(内部实现上,MS 使用了一个实现 IList 接口的 MultipleCopiesCollection 集合类型,只需要设置 CopiedItem 及 Count 两个属性,即可表现出长为 Count、每个元素都是 CopiedItem 的行为。)
TreeGrid 的虚拟化
&&& 根据之前的分析,我们已经知道表格 DataGrid 实现虚拟化都需要哪些元素,元素之间是如何交互的。而我们的 TreeGrid 控件也是模仿这个结构进行的设计,添加了相应的 TreeGridRowsPanel、TreeGridCellsPresenter、TreeGridCellsPanel 类型。最终的表格控件,经测试,给 20000 行数据,300列,都能在 0.5s 内完成渲染:
&&& 图2 虚拟化后可显示大量数据 TreeGrid
&&& 上图表格中的大量数据,只生成了少量的可视元素,最终生成的可视树结构如下:
&&& 图3 TreeGrid 虚拟化后的可视树元素
&&& 由于每一列的单元格都是随着拖动横向滚动条而生成的,所以在拖动时有一定的延迟,没有原来感觉流畅。所以当列数较少时,则没有必要打开列虚拟化。目前暂时设定为,当列数超过 50 的时候,该表格会自动打开列虚拟化功能,提升渲染性能。
未来的改进
&&& 其实,TreeGrid 作为 OEA 框架界面层的核心控件,主要是在提供 WPF 中的树型表格及一般表格功能。一般表格状态下的性能保障由虚拟化技术来实现。而在树型状态下,则主要是支持树节点的懒加载,只实例化已经开展的行,即只有展开树中的父行时,才会生成其对应的子行。如下图所示:
&&& 图4 树型表格的懒加载
&&& 树型表格状态下,暂时没有实现虚拟化。
&&& VirtualizingStackPanel 为了提高性能,它是根据 Item (项数)而不是 Pixel (象素)来计算滚动条信息。这导致了当每一行的高不统一时,竖向滚动条会计算出错,造成很差的用户体验。这也是为什么 ListBox 等控件在分组状态下,虚拟化会被关闭的原因:分组后每一项其实是 GroupItem 类型,而每个组的高度并不一致。
&&& 而 TreeGrid 中,支持行虚拟化的 TreeGridRowsPanel 是继承自 VirtualizingStackPanel 来实现的。而表格行 TreeGridRow 类则继承自 HeaderedItemsControl 类型,它的总行高应该是本行的高度加上所有子行的高度,也不是一个定值,所以现在虚拟化功能也被关闭。而当行虚拟化关闭后,由于列虚拟化实现的机制依赖最外层的 ScrollViewer,所以也被关闭。也就是说,暂时不能只打开列虚拟化,而不打开行虚拟化。
&&& 这些功能其实都是可以打开的,但是前提是必须让 TreeGridRowsPanel 继承自 VirtualizingPanel 而不是 VirtualizingStackPanel,并实现自定义行高的计算逻辑,相对复杂。考虑到目前树型表格状态下,使用懒加载在性能上已经没有什么问题,暂时就不实现虚拟化了。
&&& (另外,就算重写了行的虚拟化面板,来通过 TreeGridRow 计算出它所有子的高度,最后对需要显示的行进行实例化。也只能打开最外层 TreeGridRow 的虚拟化功能,而树可能有第二层、第三层……,这些层都无法实现虚拟化。如果要实现这些层的虚拟化,那就更复杂了……& :(& )
&&& 其实,懒加载和虚拟化技术,本质上是一样的,都是把不需要显示的元素延后实例化。 :)
&&& 由于 TreeGrid 虚拟化技术的相关设计思路主要来自 DataGrid,有些代码甚至是直接拷贝自 DataGrid,所以代码就不贴在这了。下次更新 OEA 的时候,大家就可以在开源地址中下载到了。
&&& TreeGrid 表格实现虚拟化技术,涉及到重构整个控件内部的组织结构,是本阶段 TreeGrid 重构的一个首要内容。而下一篇文章,会说一下 TreeGrid& 控件其它方面的相关重构。
阅读(...) 评论()

我要回帖

更多关于 wpf 报表 的文章

 

随机推荐