DevExpress .NET 报告 v24.1
网络报告
Blazor 报告
所有平台
云部署
可访问性
数据源
网络报告
#原生 React 报告查看器组件
我们的原生 React Report Viewer 组件利用了 DevExpress Angular Report Viewer 的内部架构和相关的辅助技术。与基于 JavaScript 包装器的解决方案相比,我们的实现提供了卓越的用户体验和更高的性能。我们的新 React Report Viewer 附带以下内置自定义功能:
工具栏自定义
JavaScript
'use client';
import React from 'react';
import ReportViewer, { Callbacks, RequestSettings } from 'devexpress-reporting-react/dx-report-viewer';
import { TemplateEngine } from 'devexpress-reporting-react/dx-report-viewer/core/template-engine';
import { ActionId } from 'devexpress-reporting/viewer/constants';
import { CustomAction } from 'devexpress-reporting/dx-webdocumentviewer';
import "devextreme/dist/css/dx.light.css";
import "@devexpress/analytics-core/dist/css/dx-analytics.common.css";
import "@devexpress/analytics-core/dist/css/dx-analytics.light.css";
import "devexpress-reporting/dist/css/dx-webdocumentviewer.css";
import styles from "./page.module.css";
export default function Home() {
const templateEngine = new TemplateEngine();
templateEngine.setTemplate('slideshow', () => (
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="0 0 24 24">
<polygon className="dxd-icon-fill" points="4,2 4,22 22,12 " />
</svg>
));
const handleCustomizeMenuActions = ({ sender, args }: { sender: any, args: any }) => {
let interval: any;
const action = new CustomAction({
text: "Run Slide Show",
imageTemplateName: "slideshow",
visible: true,
disabled: false,
selected: false,
clickAction: function () {
if (this.selected) {
clearInterval(interval);
this.selected = false;
return;
}
var model = sender.GetPreviewModel();
if (model) {
this.selected = true;
interval = setInterval(function () {
var pageIndex = model.GetCurrentPageIndex();
model.GoToPage(pageIndex + 1);
}, 2000);
}
}
});
args.Actions.push(action);
var highlightEditingFieldsAction = args.GetById(ActionId.HighlightEditingFields);
if (highlightEditingFieldsAction)
highlightEditingFieldsAction.visible = false;
};
return (
<main className={styles.main}>
<ReportViewer reportUrl="Report" templateEngine={templateEngine}>
<RequestSettings invokeAction="/DXXRDV" host="http://localhost:5065" />
<Callbacks CustomizeMenuActions={React.useCallback(handleCustomizeMenuActions,[])} />
</ReportViewer>
</main>
);
}示例:React 报告 - 自定义查看器工具栏
参数定制
以下示例代码为参数编辑器声明了一个自定义模板,并将验证规则应用于 NumberBox 组件(用于编辑“年龄”报告参数值):
JavaScript
const CustomizeParameterEditor = ({data}: {data: IEditorViewModel}) => (
<NumberBox showSpinButtons={true} value={data.value} disabled={data.disabled}>
<Validator validationRules={data.validationRules}>
</Validator>
</NumberBox>
);
export default function Home() {
const templateEngine = new TemplateEngine();
templateEngine.setTemplate('custom-parameter-editor', CustomizeParameterEditor);
const handleCustomizeParameterEditors = React.useCallback((event: any): void => {
const parameter = event.args.parameter;
const info = event.args.info;
const curYear = new Date().getFullYear();
if (parameter.type === 'CustomParameterType') {
info.validationRules = info.validationRules || [];
info.validationRules.push({
type: 'range',
min: 1900,
max: curYear,
message: `The Birth Year parameter value should be in a range from 1900 to ${curYear}.`
});
info.editor.header = "custom-parameter-editor";
}
}, []);
return (
<main className={styles.main}>
<ReportViewer reportUrl="CustomParameterReport" templateEngine={templateEngine}>
<RequestSettings invokeAction="/DXXRDV" host="http://localhost:2119/" />
<Callbacks CustomizeParameterEditors={handleCustomizeParameterEditors} />
</ReportViewer>
</main>
);
}
#原生 Angular 报告查看器
工具栏自定义 API
在此版本中,我们的Angular Report Viewer允许您根据需要自定义其内置工具栏。以下代码片段使用CustomizeMenuActions事件处理程序隐藏工具栏项:
CustomizeMenuActions(event) {
var actionSearch = event.args.GetById(ActionId.Search);
if (actionSearch)
actionSearch.visible = false;
}
var highlightEditingFieldsAction = e.GetById(DevExpress.Reporting.Viewer.ActionId.HighlightEditingFields);
if (highlightEditingFieldsAction)
highlightEditingFieldsAction.visible = false;
}以下代码片段使用相同的事件处理程序向工具栏添加自定义导出选项:
function CustomizeMenuActions(event) {
const actionExportTo = event.args.GetById(ActionId.ExportTo);
const newFormat = { format: 'NewFormat', text: 'New Format' };
if (actionExportTo) {
actionExportTo.events.on('propertyChanged', (args) => {
const formats = actionExportTo.items[0].items;
if (args.propertyName === 'items' && formats.indexOf(newFormat) === -1) {
formats.push(newFormat);
}
});
}
}OnPush 变更检测策略支持
v24.1 还增加了对OnPush 变更检测策略的支持。Angular 的 OnPush 变更检测策略通过减少不必要的渲染周期并仅在输入引用发生更改时触发变更检测来提高性能。在此更新中,您可以通过在装饰器中ChangeDetectionStrategy.OnPush添加属性将检测策略从默认更改为 ,如下所示:
changeDetection@Component
import { Component, ViewEncapsulation } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
import { DxReportViewerModule } from 'devexpress-reporting-angular';
@Component ({
selector: 'app-root',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
standalone: true,
imports: [
CommonModule,
RouterOutlet,
DxReportViewerModule
],
templateUrl: './app.component.html',
styleUrls: [...]
})
export class AppComponent {
title = 'DXReportViewerSample';
reportUrl: string = 'TestReport';
hostUrl: string = 'https://localhost:5001/';
invokeAction: string = '/DXXRDV';
}
#适用于 ASP.NET Core、Blazor、Angular 的新独立参数面板组件
我们新的报告参数面板组件根据后端提供的报告实例自动生成报告参数编辑器的布局(包括相关分组)。
该组件可满足各种使用场景,包括需要以编程方式创建报告并导出或通过邮件发送 - 而无需向最终用户显示其打印预览。我们的独立参数面板有助于减少应用程序的整体内存占用,因为它无需在后台生成报告图像并将其发送到客户端应用程序。

组件实现基于我们的报告查看器组件中的参数面板。因此,它使您可以访问与报告参数相关的同一组组件公共属性和事件。以下是 Angular 平台的示例组件定义:
<dx-report-parameters-panel class="parametersPanel" [reportUrl]="yourReportName" height="560px" width="400px"> <dxrpp-request-options [invokeAction]="invokeAction" host="http://yourhostname:port/"></dxrpp-request-options> <dxrpp-callbacks (BeforeRender)="onBeforeRender($event)"></dxrpp-callbacks> </dx-report-parameters-panel>
该面板允许您创建自定义提交按钮并处理相关的点击事件。这将使您能够序列化输入参数值,将它们发送到后端应用程序,然后将它们应用于类的实例XtraReport(在打印或导出操作之前):
onBeforeRender(event) {
this.sender = event.sender;
const panel = this.sender.GetParametersModel();
panel.buttons.push({
text: 'Export',
onClick: async () => {
const data = this.sender.SerializeParametersState();
const formData = new FormData();
formData.append('serializedParameters', data);
formData.append('reportUrl', this.reportUrl);
const result = await fetch(`${this.host}/ExportWithParameters`, {
method: 'POST',
body: formData
}).then(response => response.json());
alert(result.message);
}
}, {
text: 'Send Email',
onClick: () => {
alert('Email sent');
}
});
panel.showButtons = true;
}以下代码片段在后端应用参数值:
C#
public async Task<IActionResult> ExportWithParameters(
[FromServices]IReportParametersSerializer reportParametersSerializer,
[FromForm]string serializedParameters,
[FromForm]string reportUrl){
var report = await reportParametersSerializer.ApplyParametersStateAsync(reportUrl, serializedParameters);
report.ExportToPdf("yourFilePath");
return Ok(new { Message = "A report has been successfully exported" });
}#Web 报表设计器 - 隐藏/限制参数编辑
我们引入了一组新的 API,帮助自定义参数、参数组和参数分隔符的编辑设置。在创建一组带有强制/隐藏参数的“预设”或预定义报告时,此 API 将非常有用。
新的ParameterEditingSettings类包含以下影响属性面板、字段列表和参数编辑器的设置:
AllowEditParameterCollection - 隐藏参数添加和删除按钮。
AllowEditParameterGroups - 隐藏参数组添加和删除按钮。
AllowEditParameterSeparators - 隐藏参数分隔符添加和删除按钮。
AllowEditProperties-禁用参数和组的属性编辑器。
AllowReorderParameters - 隐藏向上和向下按钮并禁用拖放操作。
以下代码片段将 ASP.NET Core 应用程序的参数、参数组和分隔符变为只读(用户不能添加/删除参数/组/分隔符,编辑/重新排序相关属性):
Razor
@{
var designerRender = Html.DevExpress().ReportDesigner("reportDesigner")
.ParameterEditingSettings( configure => {
configure.AllowEditParameterCollection = false;
configure.AllowEditParameterSeparators = false;
configure.AllowEditParameterGroups = false;
configure.AllowEditProperties = false;
configure.AllowReorderParameters = false })
.Height("100%")
.Bind("TestReport");
@designerRender.RenderHtml()
}我们还引入了一个新CustomizeParameterProperties事件,允许您在 Web 报表设计器级别自定义特定参数或禁用/隐藏特定属性编辑器。
例如,以下代码片段隐藏所有参数的“允许空值”属性编辑器(在属性面板和参数编辑器中),并隐藏参数组的删除按钮:
function customizeParameterProperties(s, e) {
if (e.parameter) {
let allowNullInfo = e.getEditor('allowNull');
if (allowNullInfo) {
allowNullInfo.visible = false;
}
}
if (e.parameterPanelLayoutItem.layoutItemType === 'Group') {
e.editOptions.allowDelete = false;
}
}Blazor 报告
#报告查看器 - 发送电子邮件
我们创建了一个示例,使用Mailkit库从我们的 Native Blazor Report Viewer 发送电子邮件。
查看器工具栏中的“发送电子邮件”按钮将打开 DxPopup 。在“发送电子邮件”窗口中,您可以指定收件人列表、主题、附件和正文。单击“发送”按钮以使用指定的设置发送报告。
* DxPopup组件可在 ASP.NET 和 Blazor 订阅中使用。

所有平台
#SVG 导出
v24.1 附带了新的 SVG 导出选项。启用后,它允许用户将报告保存为可缩放矢量图形 (SVG) 图像的集合。这种新的导出格式将生成高质量的矢量报告页面图像,而不会损失文本内容质量。对于希望修改/共享报告图像或在网页上嵌入报告缩略图的人来说,SVG 导出将非常有用(因为 SVG 格式与现代浏览器完全兼容)。

#新的表达式函数
我们在 DevExpress Reports 中使用的标准语言语法中添加了以下新的表达式函数:
PrevRowColumnValue(string columnName)— 允许用户检索上一列/行的值。如果该记录是数据源中的第一条记录,则函数调用将返回相同的记录。
NextRowColumnValue(string columnName)— 允许用户检索下一列/行的值。如果该记录是数据源中的最新记录,则函数调用将返回相同的记录。
GroupIndex(int level)— 允许用户检索当前组索引。
CurrentRowIndexInGroup()— 允许用户检索组内的当前行索引。
函数适用于可通过表达式绑定设置其值的报表控件属性。当您需要隐藏组中的第一条或最后一条记录,或突出显示这些记录(即修改外观属性,如字体、背景色等)时,它们特别有用。当您需要在组标题中显示组编号或在组本身内显示记录编号时,获取组索引或组内的行索引很有用。PrevRowColumnValue和NextRowColumnValue函数的引入还简化了从 Microsoft SSRS 和 Crystal Reports(存在它们的对应项)的迁移。
以下示例生成带有多级编号列表的报表。为了实现此报表布局,报表控件在数据绑定表达式中使用GroupIndex和CurrentRowIndexInGroup函数(以返回组和行索引)。
下图说明了按产品类别和停产状态对信息进行分组的报告的输出(有关更多信息,请查看以下帮助主题:按索引分组编号。):

#参数本地化增强功能
借助我们内置的 DevExpress Reports 本地化引擎,使用我们的报表设计器的个人现在可以本地化所有支持平台上参数面板内显示的参数组的标题。
查找参数静态值的描述也可以本地化。
云部署
#基于 Skia 的图形引擎(非 Windows 环境)- 性能增强
我们重构了跨平台绘图引擎的实现:我们添加了字体内部缓存并优化了动态内存分配。我们的内部测试表明,在生成 1500 页的基于文本的报告(平均 25 次迭代)时,有以下改进:
创建报告文档所需的时间减少了约 20% (9 秒对 11 秒)。
将报告导出为 PDF 所需的时间减少了约 16% (7.25 秒 vs. 8.7 秒)。
将报告导出为图像所需的时间减少了约 10% (5.2 秒对 5.7 秒)。

我们还发现整体 CPU 使用率下降了约 8-10%。
注意:对于包含大量文本的大型报告文档,性能增强最为明显。
#Microsoft Azure 和 Amazon Web Services 应用程序部署教程
我们创建并发布了一系列帮助主题,旨在简化将 DevExpress Reports 支持的 Web 应用部署到 Microsoft Azure 和 AWS。教程包括:
微软 Azure
通过 Visual Studio 将 ASP.NET Core 报告应用程序部署到 Azure 应用服务 (Linux)
通过 Visual Studio/CLI 将 dockerized ASP.NET Core Reporting 应用部署到 Azure App Service (Linux)
部署具有报告功能的 Azure Functions App(基于 Linux)
使用 Azure 存储缓存来存储报告文档
亚马逊网络服务(AWS):
使用 AWS Fargate 将 Docker 化的 ASP.NET Core 报告应用程序(基于 Linux)部署到 AWS Elastic Container Service
部署 AWS Lambda 函数应用程序
创建并部署具有报告功能的 REST API 应用程序到 AWS Lambda
我们鼓励您查看这些新主题:DevExpress 报告 - 云集成。
#Microsoft Azure 报告 — 更新参考
我们重构了负责与 Azure 服务总线和 Azure 存储通信的服务的内部实现。这些服务旨在使用 DevExpress Reports 在 Microsoft Azure 上托管多实例 ASP.NET Web 表单、MVC 和 ASP.NET Core Web 应用。它们还允许您在 Azure 表和 Azure Blob 存储中缓存报告文档。我们的实现现在使用以下 NuGet 包的最新版本。
Azure.Data.Tables v12.8.3
Azure.存储.Blobs v7.17.4
Azure.Messaging.ServiceBus v12.19.1
文档:Microsoft Azure 报告 - 实施自定义存储
NuGet 包:ASP.NET Web 窗体和 MVC | ASP.NET Core
可访问性
我们现在支持以下控件的辅助工具:
本机 Blazor 报告查看器
JS 报告查看器
WinForms 报告查看器*
WPF 报告查看器*
* 我们已意识到这些问题并计划在即将发布的版本中解决它们。
我们增强了可访问性树,以确保辅助技术能够根据 WCAG 中概述的可访问性指南从用户界面元素中获取所需的信息。
辅助技术(屏幕阅读器)现在可以访问上面列出的所有控件中的文档内容。
以下控件现在完全支持键盘导航:
本机 Blazor 报告查看器
HTML5/JS 报告查看器
用户可以使用选项卡、箭头和特殊键在用户界面元素之间移动并浏览文档内容。
数据源
#SqlDataSource 向导 — 信任级别证书和加密选项
请注意,下面描述的更改已在我们当前主要版本的最新更新中可用:v23.2.5。
在将报告绑定到 MS SQL Server 实例时, 我们增强了数据源向导 中的用户体验。数据源连接屏幕现在具有屏幕截图上标记的两个新选项:

如果您无法以不同方式设置 MS SQL Server, 这些新选项/更改可让您在将报告绑定到 MS SQL Server 数据库时避免出现“证书链由不受信任的机构颁发”错误。在以下 Microsoft 主题中了解有关此错误及其原因的更多信息:证书链由不受信任的机构颁发 - SQL Server(Microsoft Learn)。
#SqlDataSource — Postgres 数据驱动程序 v7.0 支持
最初,我们希望引入Postgres 存储过程支持,但发现它们主要用于更新和删除数据库操作(SqlDataSource组件以只读模式运行)。
相反,我们修改了 Postgres 数据库连接,现在允许您在使用最新的 v7.0 数据库驱动程序时 将 DevExpress 报告和 BI 仪表板绑定到Postgres 函数。
#JsonDataSource — System.Text.Json NuGet 包的使用
使用 v24.1,DevExpress Reports 和 BI Dashboard 将利用System.Text.Jsonassembly/NuGet 包中的功能(默认情况下)。此更改受到安全考虑和 Microsoft 内置库提供的改进性能的影响。此包是 .NET 的一部分,此更改仅适用于 .NET 产品线;基于 .NET Framework 的产品保持不变,并将继续使用包中的功能Newtonsoft.Json。
如果由于任何原因,您无法在基于 .NET 的应用程序中利用 System.Text.Json 功能,则可以将DevExpress.DataAccess.Native.Json.JsonLoaderHelper.JsonProcessingLibrary* 属性设置为NewtonsoftJson并继续使用 Newtonsoft.Json 库。
*注意:我们提供此属性是为了向后兼容。一旦迁移完成,它将从未来版本的源代码中删除。
我们还鼓励您相应地更新您的应用程序。
重大变更描述:使用 System.Text.Json 来处理 JsonDataSource(DashboardJsonDataSource)组件,而不是 Newtonsoft.Json 库
渝公网安备50010702505508