使用WPF进行打印/报告的最佳方法是什么?[关闭]


70

我有一个即将到来的项目,该项目将必须能够从其数据中打印简单的报告。这将是基于WPF的,我想知道该走哪条路。

我知道WPF引入了自己的打印技术(基于XPS),看起来很容易使用。但是,我不知道要使用ReportViewer控件并将其嵌入Windows Forms宿主控件是否会更容易,因为这将使用户能够导出为多种格式以及进行打印。

有没有人从WPF打印/报告过任何经验?您会向哪个方向推荐?


SimpleWPFReporting使您能够利用WPF XAML的全部功能来创建任何报告。SimpleWPFReporting将负责将其导出为PDF或进行打印。
马克斯

Answers:


25

我们遇到了同样的问题,并最终使用了RDLC / ReportViewer。(我不知道)没有本地的WPF报告工具,并且RDLC使用起来非常简单并且是免费的。它的运行时开销很小(大约2Mb),但是您必须记住要分发它,因为它不是.NET Framework的一部分。


42

RDL的局限性

我最初与RDLC / ReportViewer一起使用WPF进行打印,但发现它的局限性很大。我发现的一些限制是:

  • RDL只能创建最无聊的报告
  • 使用RDL创建报表要比直接在WPF中做更多的工作:与Expression Blend和仅在表中进行RDL交易相比,设计工具非常原始
  • 我没有使用ControlTemplates,DataTemplates,Styles等的能力
  • 我的报告字段和列无法根据数据大小有效地调整大小和重新排列
  • 图形必须作为图像导入-无法将其绘制或编辑为矢量
  • 项目的位置需要代码背后而不是数据绑定
  • 缺乏转换
  • 非常原始的数据绑定

从WPF直接打印非常容易

由于这些限制,我研究了使用纯WPF创建报表的过程,发现它确实非常琐碎。WPF允许您实现自己的DocumentPaginator可以生成页面的子类。

我开发了一个简单的DocumentPaginator子类,该子类可以获取任何Visual图像,分析视觉树并隐藏选定的元素以创建每个页面。

DocumentPaginator详细信息

这是我的DocumentPaginator子类在初始化期间(在获取第一个PageCount时或在第一次GetPage()调用时调用)的作用:

  1. 扫描可视树并为ItemsControls中的所有滚动面板绘制地图
  2. 从最外层开始,使ItemsControls中的项目从最后到第一个不可见,直到Visual无需滚动即可适合单个页面。如果最外面的东西不能足够减少,请减少内部面板,直到它成功或每个级别只有一个项目为止。将可见项目集记录为第一页。
  3. 隐藏第一页上已经显示的最低级别的项目,然后使后续项目可见,直到它们不再适合页面为止。将除最后添加的项目外的所有内容记录为第二页。
  4. 对所有页面重复该过程,将结果存储在数据结构中。

我的DocumentPaginator的GetPage方法如下:

  1. 在初始化期间生成的数据结构中查找给定的页码
  2. 如数据结构所示,在可视树中隐藏和显示项目
  3. 设置PageNumber和NumberOfPages附加属性,以便报表可以显示页码
  4. 刷新分派器(Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => {} ));)以完成所有后台渲染任务
  5. 创建矩形的页面大小,该页面的VisualBrush是要打印的视觉对象
  6. 测量,排列和更新矩形,然后将其返回

事实证明,这是非常简单的代码,几乎可以将我用WPF创建的所有内容转换为页面并进行打印。

其他报告支持

现在,我的分页器正在工作,我不必再为我为屏幕或纸张创建WPF内容而烦恼了。实际上,通常我为数据输入和编辑而构建的UI也非常适合打印。

从那里,我添加了一个简单的工具栏和一些代码,从而形成了一个完整的基于WPF的报表系统,其功能远胜于RDL。我的报告代码可以导出到文件,打印到打印机,剪切/粘贴页面图像以及Excel的剪切/粘贴数据。我也可以通过单击复选框将任何UI切换到“打印视图”,以查看打印后的外观。所有这一切仅用几百行C#和XAML!

在这一点上,我认为RDL唯一不具备我的报告代码的功能是能够生成格式化的Excel电子表格。我可以看到可以怎么做,但是到目前为止,没有必要-仅剪切和粘贴数据就足够了。

根据我的经验,我的建议是写一个分页器,然后开始使用WPF本身创建报告。


6
非常有趣,因为我正在考虑删除RDLC。您是否发布了文档分页器的任何代码?
Eduardo Molteni

2
您能对此进行扩展吗?也许有一些简短的代码/ xaml示例?
Alex Hope O'Connor 2012年


6
“直接从WPF打印非常容易”。真假的啊?我已经投入了很多时间和精力来实现这一目标,并且通过任何想象力来对数据绑定的数据网格进行分页都不容易。恐怕细节中的魔鬼,直到我看到一些,这个答案不是很有用。
Manos Dilaverakis

1
这里,这里,@ RayBurns。让我们看一个github仓库,以便我们可以为这个令人赞叹的实现做出贡献。
Killnine 2014年





1

我最近完成了开发自己的报告系统的任务,该报告系统基本上由设计环境和数据源管理器组成。首要任务是开发类似WYSWIG的设计环境。我已经使用GDI +进行了此操作,甚至没有打扰打印,因为它出来的结果是打印/生成打印预览比我预期的要容易得多,通常只需要将屏幕上的所有内容绘制到打印事件的图形对象即可。

我认为在WPF的情况下会很相似,因此您只需要担心在屏幕上显示报告,而打印只需几行代码。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.