从 WPF 打印/报告的最佳方法是啥? [关闭]
Posted
技术标签:
【中文标题】从 WPF 打印/报告的最佳方法是啥? [关闭]【英文标题】:What's the best approach to printing/reporting from WPF? [closed]从 WPF 打印/报告的最佳方法是什么? [关闭] 【发布时间】:2010-09-15 21:30:12 【问题描述】:我有一个即将进行的项目,它必须能够从其数据中打印简单的报告。它将是基于 WPF 的,我想知道该走哪条路。
我知道 WPF 引入了自己的打印技术(基于 XPS),看起来很容易使用。但是,我的一部分想知道使用 ReportViewer 控件并将其嵌入到 Windows 窗体宿主控件中是否更容易,因为这将使用户能够导出为各种格式以及打印。
有没有人有从 WPF 打印/报告的经验?你会推荐哪个方向?
【问题讨论】:
SimpleWPFReporting 使您能够使用 WPF XAML 的全部功能创建任何报告。 SimpleWPFReporting 将负责将其导出为 PDF 或打印。 【参考方案1】:RDL 的限制
我最初使用 RDLC/ReportViewer 来使用 WPF 进行打印,但发现它非常有限。我发现的一些限制是:
RDL 只能创建最无聊的报告 与直接使用 WPF 相比,使用 RDL 创建报告的工作量要大得多:与 Expression Blend 和 RDL 仅在表格中处理相比,设计工具非常原始 我无法使用 ControlTemplates、DataTemplates、Styles 等 我的报表字段和列无法根据数据大小有效调整大小和重新排列 图形必须作为图像导入 - 不能作为矢量绘制或编辑 项目的定位需要代码隐藏而不是数据绑定 缺少转换 非常原始的数据绑定直接从 WPF 打印非常简单
由于这些限制,我研究了使用纯 WPF 创建报告,发现它真的很简单。 WPF 允许您实现自己的DocumentPaginator
子类,可以生成页面。
我开发了一个简单的 DocumentPaginator 子类,它接受任何 Visual,分析可视树,并隐藏选定的元素以创建每个页面。
DocumentPaginator 详细信息
这是我的 DocumentPaginator 子类在初始化期间所做的事情(在获取第一个 PageCount 时或在第一次 GetPage() 调用期间调用):
-
扫描可视化树并制作 ItemsControls 内所有滚动面板的地图
从最外面开始,使 ItemsControls 中的项目从最后到第一个不可见,直到 Visual 适合单个页面而无需滚动。如果最外面的面板不能足够减少,则减少内部面板,直到成功或每个级别只有一个项目。将可见项目集记录为第一页。
隐藏已在第一页显示的最低级别项目,然后使后续项目可见,直到它们不再适合页面。将最后添加的项目以外的所有项目记录为第二页。
对所有页面重复该过程,将结果存储在数据结构中。
我的DocumentPaginator的GetPage方法如下:
-
在初始化时生成的数据结构中查找给定的页码
在可视化树中隐藏和显示项目,如数据结构所示
设置 PageNumber 和 NumberOfPages 附加属性,以便报表可以显示页码
刷新调度程序 (
Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => ));
) 以完成所有后台渲染任务
创建一个与页面大小相同的矩形,其 VisualBrush 是正在打印的视觉对象
测量、排列和更新布局矩形,然后返回它
结果证明这是一段非常简单的代码,让我可以将几乎所有可以使用 WPF 创建的内容转换成页面并打印出来。
其他报告支持
现在我的分页器正在工作,我不再需要非常担心我是为屏幕还是纸张创建 WPF 内容。事实上,我为数据输入和编辑构建的 UI 通常也非常适合打印。
从那里我添加了一个简单的工具栏和一些代码,从而形成了一个基于 WPF 构建的成熟报告系统,它比 RDL 功能强大得多。我的报告代码可以导出到文件、打印到打印机、剪切/粘贴页面图像以及剪切/粘贴 Excel 数据。我还可以通过单击复选框将我的任何 UI 切换到“打印视图”,以查看打印后的外观。只需几百行 C# 和 XAML 即可完成所有这些!
在这一点上,我认为 RDL 的唯一功能是我的报告代码不具备的功能是能够生成格式化的 Excel 电子表格。我可以看到如何做到这一点,但到目前为止还没有必要 - 仅剪切和粘贴数据就足够了。
根据我的经验,我的建议是编写一个分页器,然后开始使用 WPF 本身来创建您的报告。
【讨论】:
非常有趣,因为我正在考虑放弃 RDLC。您是否发布了文档分页器的任何代码? 你能扩展一下吗?也许有一些简短的代码/xaml 示例? 找到这个:codeproject.com/Articles/138233/… “直接从 WPF 打印非常简单”。真的吗?我已经投入了大量的时间和精力来实现这一点,并且对数据绑定的数据网格进行分页并不是一件容易的事。恐怕魔鬼在细节中,直到我看到一些,这个答案不是很有用。 这里,这里,@RayBurns。让我们看看一个 github 存储库,这样我们就可以为这个听起来很棒的实现做出贡献。【参考方案2】:我们遇到了同样的问题,最终暂时使用了 RDLC/ReportViewer。没有本机 WPF 报告工具(据我所知),RDLC 使用起来非常简单,而且是免费的。它的运行时开销很小(大约 2Mb),但您必须记住分发它,因为它不是 .NET Framework 的一部分。
【讨论】:
【参考方案3】:看http://wpfreports.codeplex.com/
【讨论】:
我在 nullskull 上找到了一个 artikel,它逐步解释了如何使用相同的方法创建 WPF 报表引擎。 看起来不错,但在 2020/11/11 项目描述中仍然说“这是一个非常早期的 alpha 版本,不打算在生产环境中使用。”【参考方案4】:看看PdfReports。它是一个代码优先报告引擎,构建在 iTextSharp 和 EPPlus 库之上。它与 .NET 3.5+ Web 和 Windows 应用程序兼容。
【讨论】:
iTextSharp 许可证 :( 该库还有一个 .NET Core/Full .NET 版本,具有 LGPL 许可证:github.com/VahidN/PdfReport.Core【参考方案5】:Scryber 怎么样?它允许使用 xml 定义 PDF 报告模板并在运行时绑定到应用程序中的数据。 http://scryber.codeplex.com/
【讨论】:
【参考方案6】:要详细说明 Ray Burns 的答案,如果您正在寻找实现示例,请参阅: Custom Data Grid Document Paginator
这是一个很好的起点。
【讨论】:
【参考方案7】:我最近完成了开发自己的报告系统的任务,主要包括设计环境和数据源管理器。第一项任务是开发类似 WYSWIG 的设计环境。我已经使用 GDI+ 完成了这项工作,甚至不用担心打印,因为打印/生成打印预览比我预期的要简单,通常只需将屏幕上的所有内容绘制到打印事件的图形对象即可。
我认为在 WPF 的情况下它会是相似的,所以您应该担心的只是在屏幕上显示您的报告,打印只需几行代码。
【讨论】:
【参考方案8】:在没有进入关于 WPF 未来的完整政治讨论的情况下,我们发现最好的选择是将 ReportViewer 包装在 Windows 窗体主机控件中。
http://blog.pineywoodstech.com/index.php/2012/01/using-microsoft-reportviewer-with-wpf/
【讨论】:
以上是关于从 WPF 打印/报告的最佳方法是啥? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
在 Java 应用程序中读取 XML 文件的最佳/最简单方法是啥? [关闭]