Custom Control Integration
As you may already know, we've made custom report control registration within DevExpress Reports much easier. To address the needs of web developers, v23.1+ includes streamlined custom control registration support (implemented at the server level). If your solution requires the use of custom report controls, all you'll need to do is add controls to a custom controls collection in the server-side report design model. JavaScript functions, properties, and values will be generated automatically.
Label with Rounded Corners — a Custom Control for Multiple Platforms
Let's create a sample application (for all supported web platforms) to help illustrate the flexibility of our custom report control registration process.
- ASP.NET Web Forms
- ASP.NET MVC
- ASP.NET Core
- Angular
- Report Designer for Blazor Server (based on JavaScript)
The following GitHub examples demonstrate creation/use of custom report controls:
- How to Create a Custom DevExpress Report Control
- Reporting for WinForms - Create a Custom Progress Bar Control
The first example is versatile: explore our implementation to learn how to create custom report controls with rounded corners — XRRoundLabel
and XRRoundPanel
, and the Swiss QR Bill control. Follow the steps below to register the XRRoundLabel control in a web application.
- Download the project from GitHub.
- Open the Blazor sample solution and add the DevExpress.XtraReports.CustomControls.RoundedControls project to the solution. Reference the project in the Blazor sample project.
- Rebuild the solution.
- Add the
XRRoundControl
type to the Report Designer collection of custom controls:
@page "/reportdesigner"
<DxReportDesigner ReportName="TestReport" Height="calc(100vh - 130px)"
Width="100%" AllowMDI="true"
CustomControlTypes="@customTypes">
<DxReportDesignerWizardSettings UseFullscreenWizard="true" />
</DxReportDesigner>
@code {
List<Type> customTypes = new List<Type> {
typeof(DevExpress.XtraReports.CustomControls.RoundBordersControls.XRRoundLabel) };
}
Finally, launch the application. You will see that the custom control appears in the toolbar (with the default question mark icon):
Icon, Tooltip, and Toolbar Position — Client-Side Configuration
To change the default icon, add an svg template with a name that matches the fully qualified type name of the custom control:
<script type="text/html" id="dxrd-svg-toolbox-devexpress_xtrareports_customcontrols_roundborderscontrols_xrroundlabel">
<svg viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#a)">
<path d="M22.7 28H27L18.3 4h-4.7L5 28h4.3l2.2-6h9.1l2.1 6Zm-9.8-10L16 9.4l3.1 8.6h-6.2Z" fill="#1177D7"/>
<rect x="1" y="1" width="30" height="30" rx="5" stroke="#727272" stroke-width="2"/>
</g>
<defs>
<clipPath id="a">
<path fill="#fff" d="M0 0h32v32H0z"/>
</clipPath>
</defs>
</svg>
</script>
To change the tooltip and specify the location in the toolbar, handle the client-side CustomizeToolbox
event as follows:
@page "/reportdesigner"
<DxReportDesigner ReportName="TestReport" Height="calc(100vh - 130px)"
Width="100%" AllowMDI="true"
CustomControlTypes="@customTypes">
<DxReportDesignerWizardSettings UseFullscreenWizard="true" />
<DxReportDesignerCallbacks CustomizeToolbox="onCustomizeToolbox" />
</DxReportDesigner>
@code {
List<Type> customTypes = new List<Type> {
typeof(DevExpress.XtraReports.CustomControls.RoundBordersControls.XRRoundLabel) };
}
function onCustomizeToolbox(s,e){
var info = e.ControlsFactory.getControlInfo("DevExpress.XtraReports.CustomControls.RoundBordersControls.XRRoundLabel");
var labelInfo = e.ControlsFactory.getControlInfo("XRLabel");
info.displayName = "Rounded Label";
info.toolboxIndex = labelInfo.toolboxIndex - 1;
info.group = labelInfo.group;
}
Start the application to review changes:
If you drag a control from the toolbar onto the designer surface, the control is rendered as expected (with rounded corners):
While our modification appears on screen, after switching to Print Preview mode we see that the control is not printed as a label with rounded corners (it's printed as a simple label). First, this happens because the report document is generated on the server (rendered to the RoundLabelBrick
class rather than to one of the brick classes known to the document generation engine). The RoundLabelBrick
class must be registered in the internal BrickFactory
. Accordingly, we'll need to call the EnsureCustomBrick
method in the Program.cs file:
DevExpress.XtraReports.CustomControls.RoundedCustomControl.EnsureCustomBrick();
Note: For the Progress Bar control, the BrickFactory
registration step can be ignored, since the CreateBrick
method for this control returns an instance of PanelBrick
, which is a built-in and known. Output is illustrated in the following video. It demonstrates the XRRoundLabel control in the Report Designer, a custom BorderCornerRadius
property, and the custom control within the Print Preview:
The registration technique is basically the same for other web-based platforms. Note the differences in how custom control type arrays are passed:
ASP.NET MVC
@Html.DevExpress().ReportDesigner(settings => {
settings.Name = "ReportDesigner1";
settings.CustomControlTypes.Add(typeof(DevExpress.XtraReports.CustomControls.RoundBordersControls.XRRoundLabel));
}).BindToUrl("TestReport").GetHtml()
ASP.NET Core
For ASP.NET Core applications, custom control types are passed to a designer model created in the controller (using a model builder that implements the IReportDesignerModelBuilder
interface):
public class HomeController : Controller {
// ...
public IActionResult Designer(
[FromServices] IReportDesignerModelBuilder reportDesignerModelBuilder,
[FromQuery] string reportName) {
reportName = string.IsNullOrEmpty(reportName) ? "TestReport" : reportName;
var designerModel = reportDesignerModelBuilder
.Report(reportName)
.CustomControls(typeof(DevExpress.XtraReports.CustomControls.RoundBordersControls.XRRoundLabel))
.BuildModel();
return View(designerModel);
}
}
DevExpress components for JavaScript frameworks (Angular, React, Vue) are based on aj ASP.NET Core server-side application. This means no client-side code is needed. You have to add custom control types to the ASP.NET Core backend as demonstrated in the code snippet above (and include an SVG template for the toolbar icon in the client application). Yes, it's as simple as that.
In this particular instance, we must call the DevExpress.XtraReports.CustomControls.RoundedCustomControl.EnsureCustomBrick
method at application startup in all of our sample projects.
Custom Expression Function Integration
To register a custom expression function in a web application, you need to call one of the following registration methods when you start the application.
Registration Methods
Scope: Only Reporting Components
The CustomFunctions.Register method allows you to use the specified custom functions in expression bindings and calculated fields. Custom functions are displayed in the list of available functions in the Reporting Expression Editor.
DevExpress.XtraReports.Expressions.CustomFunctions.Register(new CustomFormatFunction());
Scope: All DevExpress Components — Data Source Wizard, Query Builder, and Others
If you want your custom function to be available for SQL queries in the Data Source Wizard or elsewhere in the application (outside of our Reporting components), implement the ICustomFunctionOperatorFormattable interface and register the function using the CriteriaOperator.RegisterCustomFunction method. For more information, review the following help topic: Custom Functions.
CriteriaOperator.RegisterCustomAggregate(new CountDistinctCustomAggregate());
Sample Implementation (GitHub): Reporting for ASP.NET Core - How to Implement a Custom Function in the Expression Editor.
What’s New in v23.1 and v23.2
If you have yet to review the features/capabilities introduced in 2023, please visit the following webpages: Reporting, What's New in v23.2 | Reporting, What's New in v23.1.