我有一个即将开展的项目,必须能够从其数据中打印简单的报告.它将基于WPF,我想知道要走哪条路.
我知道WPF引入了自己的打印技术(基于XPS),看起来非常容易使用.但是,我的一部分想知道使用ReportViewer控件并将其嵌入Windows窗体主机控件是否更容易,因为这将使用户能够导出为各种格式以及打印.
有没有人有WPF打印/报告的经验?你会推荐哪个方向?
RDL的局限性
我最初使用RDLC/ReportViewer进行WPF打印,但发现它非常有限.我发现的一些限制是:
RDL只能创建最无聊的报告
使用RDL创建报告比使用直接WPF创建报告要多得多:与Expression Blend相比,设计工具非常原始,RDL仅在表格中处理
我没有能力使用ControlTemplates,DataTemplates,Styles等
我的报告字段和列无法根据数据大小有效调整大小和重新排列
图形必须作为图像导入 - 它不能作为矢量绘制或编辑
项目的定位需要代码隐藏而不是数据绑定
缺乏变革
非常原始的数据绑定
直接从WPF打印非常容易
由于这些限制,我考虑使用纯WPF创建报告,并发现它确实非常简单.WPF允许您实现自己的DocumentPaginator
子类,可以生成页面.
我开发了一个简单的DocumentPaginator子类,它接受任何Visual,分析可视树,并隐藏选定的元素来创建每个页面.
DocumentPaginator详细信息
这是我的DocumentPaginator子类在初始化期间所做的事情(在第一次获取PageCount时或在第一次GetPage()调用期间调用):
扫描可视树并在ItemsControls中创建所有滚动面板的地图
从最外层开始,使ItemsControls中的项不可见,直到Visual适合单个页面而不需要滚动.如果最外层不能减小,则减少内板直到成功或每层只有一个项目.将可见项目集记录为第一页.
隐藏已在第一页上显示的最低级别项目,然后使后续项目可见,直到它们不再适合页面.记录除最后添加的项目之外的所有项目作为第二页.
对所有页面重复此过程,将结果存储在数据结构中.
我的DocumentPaginator的GetPage方法如下:
在初始化期间生成的数据结构中查找给定的页码
隐藏和显示可视树中的项目,如数据结构中所示
设置PageNumber和NumberOfPages附加属性,以便报告可以显示页面编号
刷新Dispatcher(Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => {} ));
)以完成任何后台渲染任务
创建一个Rectangle,其大小与VisualBrush是正在打印的可视化页面相同
测量,排列和更新矩形,然后返回它
事实证明这是非常简单的代码,并且允许我将使用WPF创建的任何内容转换为页面并打印它.
额外的报告支持
现在我的分页器正在工作,我不再需要担心我是否正在为屏幕或纸张创建WPF内容.实际上,我为数据输入和编辑构建的UI通常也非常适合打印.
从那里我添加了一个简单的工具栏和一些代码,从而形成了一个围绕WPF构建的成熟的报告系统,它比RDL更强大.我的报告代码可以导出到文件,打印到打印机,剪切/粘贴页面图像,以及剪切/粘贴Excel数据.我还可以通过单击复选框将我的任何UI切换到"打印视图",以查看打印时的外观.所有这些只需几百行C#和XAML!
此时我认为RDL的唯一功能是我的报告代码没有能够生成格式化的Excel电子表格.我可以看到如何做到这一点,但到目前为止还没有必要 - 单独剪切和粘贴数据就足够了.
根据我的经验,我的建议是编写一个分页器,然后开始使用WPF本身来创建报告.
我们遇到了同样的问题,现在最终使用RDLC/ReportViewer.没有原生的WPF报告工具(我知道)和RDLC使用非常简单,而且是免费的.它的运行时开销很小(约2Mb),但您必须记住分发它,因为它不是.NET Framework的一部分.
看看http://wpfreports.codeplex.com/