71

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

我知道 WPF 引入了自己的打印技术(基于 XPS),看起来很容易使用。然而,我的一部分想知道使用 ReportViewer 控件并将其嵌入到 Windows 窗体主机控件中是否更容易,因为这将使用户能够导出为各种格式以及打印。

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

4

8 回答 8

43

RDL 的局限性

我最初使用 RDLC/ReportViewer 来使用 WPF 进行打印,但发现它非常有限。我发现的一些限制是:

  • RDL 只能创建最无聊的报告
  • 与直接使用 WPF 相比,使用 RDL 创建报告的工作量要多得多:与 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 ( Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => {} ));) 以完成任何后台渲染任务
  5. 创建一个与其 VisualBrush 是正在打印的视觉对象的页面大小相同的 Rectangle
  6. 测量、排列和更新布局矩形,然后返回它

结果证明这是非常简单的代码,并且允许我将几乎所有可以使用 WPF 创建的内容转换为页面并打印出来。

额外的报告支持

现在我的分页器正在工作,我不再需要非常担心我是为屏幕还是纸张创建 WPF 内容。事实上,我为数据输入和编辑构建的 UI 通常也非常适合打印。

从那里我添加了一个简单的工具栏和一些代码,从而产生了一个围绕 WPF 构建的成熟报告系统,它比 RDL 功能强大得多。我的报告代码可以导出到文件、打印到打印机、剪切/粘贴页面图像以及剪切/粘贴 Excel 数据。我还可以通过单击复选框将我的任何 UI 切换到“打印视图”,以查看打印后的外观。所有这一切都在几百行 C# 和 XAML 中!

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

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

于 2010-05-13T20:56:10.627 回答
25

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

于 2008-10-08T13:08:40.743 回答
8

看看http://wpfreports.codeplex.com/

于 2010-05-21T20:37:18.553 回答
3

看看PdfReports。它是一个代码优先报告引擎,构建在 iTextSharp 和 EPPlus 库之上。它与 .NET 3.5+ Web 和 Windows 应用程序兼容。

于 2012-10-09T10:28:40.303 回答
3

斯克里伯呢?它允许使用 xml 定义 PDF 报告模板并在运行时绑定到应用程序中的数据。http://scryber.codeplex.com/

于 2013-04-24T18:40:55.310 回答
2

要详细说明 Ray Burns 的答案,如果您正在寻找实现示例,请参阅: 自定义数据网格文档分页器

这是一个很好的起点。

于 2012-12-07T00:20:28.207 回答
1

我最近完成了开发自己的报告系统的任务,主要包括设计环境和数据源管理器。第一项任务是开发类似 WYSWIG 的设计环境。我已经使用 GDI+ 完成了这项工作,甚至不用担心打印,因为打印/生成打印预览比我预期的要简单,通常只需将屏幕上的所有内容绘制到打印事件的图形对象即可。

我认为在 WPF 的情况下它会是相似的,所以你应该担心的只是在屏幕上显示你的报告,打印只需要几行代码。

于 2008-10-08T12:29:57.670 回答
0

无需对 WPF 的未来进行全面的政治讨论,我们发现的最佳选择是将 ReportViewer 包装在 Windows 窗体主机控件中。

http://blog.pineywoodstech.com/index.php/2012/01/using-microsoft-reportviewer-with-wpf/

于 2012-07-17T18:39:46.373 回答