从 WPF 打印/报告的最佳方法是什么? [关闭]

2024-05-05

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

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

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


RDL 的局限性

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

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

直接从 WPF 打印非常简单

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

我开发了一个简单的 DocumentPaginator 子类,它采用任何视觉对象、分析视觉对象树并隐藏选定的元素来创建每个页面。

文档分页器详细信息

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

  1. 扫描视觉树并制作 ItemsControls 内所有滚动面板的地图
  2. 从最外层开始,使 ItemsControls 中的项目从最后到第一个不可见,直到视觉对象适合单个页面而无需滚动。如果最外面的面板不能减少得足够多,则减少内部面板,直到成功或每一层只有一个项目。将可见项目集记录为第一页。
  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 本身来创建报告。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 WPF 打印/报告的最佳方法是什么? [关闭] 的相关文章

随机推荐

  • 在Oracle中,是否可以将以逗号分隔的非常大的字符串(clob)转换为具有更好性能的表

    我需要通过逗号分隔符将非常大的 clob 字符串转换为表 下面的函数需要很长时间 有没有返回表的快速函数 create or replace FUNCTION UDF STRSPLIT2 P STR IN CLOB P DELIM IN V
  • 如何在点击时从 webview 获取 URL

    我怎样才能获得 点击的URL webview在其点击事件上 Override public void onClick View v if v getId R id webview Here i want to get clicked url
  • n 二叉树的后序遍历

    我需要以下代码的帮助来回答 我正在尝试使用堆栈而不是递归在 n 叉树上执行后序遍历 因为 python 有 1000 次递归的限制 我找到了相同的预序遍历代码 https www geeksforgeeks org iterative pr
  • Ubuntu 16.04 中 kubeadm join 命令每次都会超时

    我正在使用 Ubuntu 16 04 Xenial 但我遇到了一个问题kubeadm加入时nodes to my master 在加入一个node to my master 我不断遇到超时问题 discovery Failed to req
  • 动态添加变量名称值对到 JSON 对象

    我有一个充满 ips 的 json 对象 例如 var ips 然后我将 ip 对象添加到该对象 如下所示 ips ipID 然后我需要向每个 ip 添加动态 变量名称值对 所以我使用这样的代码 var name var value var
  • 下标的使用不明确

    该代码块以前可以工作 但现在不行了 我在纬度和经度变量上收到错误 下标 的使用不明确 这是怎么回事 这是因为 Swift 更新吗 func showPrecincts var urlBoundaries http www oklahomad
  • 从 Storm Bolt 将行插入 HBase

    我希望能够从分布式 非本地 Storm 拓扑将新条目写入 HBase 有一些 GitHub 项目提供以下任一功能 HBase 映射器 https github com ptgoetz storm hbase or 预制风暴螺栓 https
  • 使用 Python 3 从 Twitter API 检索请求令牌

    我正在尝试使用 Python 3 与 Twitter API 交互 以返回页面的链接 该页面为我提供了用于请求访问令牌的 PIN 码 详细信息如下 https dev twitter com docs auth pin based auth
  • postgresql 中带有分组的嵌套聚合函数

    我正在尝试使用嵌套聚合函数和分组来获得总和的平均值 我想做的是 SELECT AVG SUM x GROUP BY y WHERE GROUP BY 也就是说 对于返回的每一行 我希望其中一个字段是总和的平均值 其中每个总和都位于 y 相同
  • 如何将 Properties.Settings.Default 的副本保存到变量?

    我有一个 恢复默认值 选项对话框中的按钮 并且想要恢复仅在此表单中受影响的值 而不是整个 Properties Settings Default 所以我尝试 var backup Properties Settings Default Pr
  • 如何返回空实体的响应状态 405?

    如何在 java REST 中返回带有空实体的响应状态 405 POST Path path public Response createNullEntity return Response created null status 405
  • 如何将标签放在 Flutter DataColumn 小部件中?

    我可以将 DataCell 放在 DataRow 中居中 但是对于 DataColumn 标签如何做到这一点 我希望第一个 DataColumn 左对齐 其余的居中 将标签包裹在 Center 小部件中不会生效 new DataColumn
  • MS-Access:合并彼此“下方”的两个表

    我的 Access 数据库中有两个表 它们看起来像这样 Table1 Kabelnummer Column1 Column2 Column3 1 x x x 2 x x x
  • Python:如何检索每年的谷歌学术引用?

    我正在尝试从 Google Scholar 个人资料中检索信息 我有url from bs4 import SoupStrainer BeautifulSoup from urllib2 import Request urlopen url
  • 我可以在 Android 上使用带有文本视图的列表视图和图像图标吗

    我需要一个像下面的 Android 应用程序那样的列表视图 由于我无法发布图片 所以应该是这样的 图片在这里 一些自由文本 用户名等 这是你的任务 任务1 gt 任务2 gt 任务 1 和任务 2 是将从数据库动态获取的列表 我试图拥有一个
  • 在Java中运行命令行[重复]

    这个问题在这里已经有答案了 有没有办法在 Java 应用程序中运行此命令行 java jar map jar time rel test txt debug 我可以用命令运行它 但我无法在 Java 中运行它 Runtime rt Runt
  • 将大块位图转换为 3 维位图

    Problem 我需要这个大量的数据作为输入 对于基于C的arduino 这是上面示例中所需格式的大量数据 const byte bitmap 8 8 0xFF 0x81 0x81 0x81 0x81 0x81 0x81 0xFF 0x81
  • 如何在点击 Qtablewidget 单元格时获取放置在该单元格中的小部件的行号?

    我正在尝试的是当用户选择项目时获取 QcomboBox 的行号 虽然使用它很容易获得单元格的列和行 cellClicked int int 信号 但仅当单元格上没有小部件时才有效 那么如果单元格中放置了小部件 如何获取行号 Note 所有组
  • SVG 视图框显示屏幕外项目

    我正在使用 HTML5 制作游戏svg标签为图形提供多分辨率显示 游戏的大部分内容已经完成 但在测试中我刚刚遇到了一个主要错误 其中涉及 SVG 对象可见 尽管在非本机分辨率下位于视图框之外 我不确定这是否是我的代码或浏览器本身的缺陷 Go
  • 从 WPF 打印/报告的最佳方法是什么? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi