Skip to main content
A newer version of this page is available. .
All docs
V20.2

Customize the Report Designer Toolbox

  • 6 minutes to read

This topic explains how to create a custom report control inherited from the XRLabel control and register the control in the End-User Report Designer Toolbox in the ASP.NET Core Reporting application.

View Example: Custom Report Control in the Web End User Designer Toolbox in ASP.NET Core Application

To get started with this tutorial, create a new application as described in the following help topic: Create an ASP.NET Core Application with a Report Designer.

Create and Register a Custom Control in Visual Studio

To create a custom label control, do the following:

  1. Add a new class (the CustomLabel class in this example), derive it from the XRLabel class, and declare a new property. Override the PutStateToBrick protected method to assign the value to the VisualBrick.Text property:

    using DevExpress.Utils.Serializing;
    using DevExpress.XtraPrinting;
    using DevExpress.XtraReports.UI;
    using System.ComponentModel;
    
    namespace YourNamespace
    {
        public class NumericLabel : XRLabel
        {
            [Browsable(true), Bindable(false), Category("Data")]
            [XtraSerializableProperty]
            [DefaultValue("")]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
            EditorBrowsable(EditorBrowsableState.Always)]
            public int Number { get; set; }
    
            // Render the control in the Designer's Preview and in the document.
            protected override void PutStateToBrick(VisualBrick brick, PrintingSystemBase ps)
            {
                base.PutStateToBrick(brick, ps);
                brick.Text = this.Number.ToString();
            }
        }
    }
    

Note

The Visual Studio Report Designer in ASP.NET project does not display a custom control in the Toolbox.

Register a Custom Control in the Web End-User Report Designer

The following steps demonstrate how to register a custom control in the Web Report Designer Toolbox.

  1. Add a new NumericLabel folder to the project. Create two nested folders - js and css.
  2. Add a control’s icon to the css folder. The icon is an image file (PNG format, 24x24 pixels) that is shown in the Report Designer Toolbox.
  3. Add the custom-label.css file to the css folder with the following content:

    .dxrd-image-yournamespace_numericlabel {
        background-image: url(NumericLabel.png);
        background-repeat: no-repeat;
    }
    

    Note

    The CSS class name is based on the following pattern:

    .dxrd-image-<namespace in lowercase>_<class name>

  4. Create a content template for the custom control. For this, add the custom-label-content.html file to the CustomLabel folder with the following content:

    <script type='text/html' id='custom-label-content'>
        <div data-bind="styleunit: { lineHeight: contentSizes().height / _context.zoom() }" style="box-sizing: border-box; 
                                     letter-spacing: normal; width: 100%">
            <div class="dxrd-control-content" data-bind="text: displaySomeProperty, style: contentCss"></div>
        </div>
    </script>
    
  5. Add the numeric-label.js file to the NumericLabel/js folder with the following JavaScript code:

    // Implement the __extends function.
    var __extends = (this && this.__extends) || (function () {
        var extendStatics = function (d, b) {
            extendStatics = Object.setPrototypeOf ||
                ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
                function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
            return extendStatics(d, b);
        };
        return function (d, b) {
            extendStatics(d, b);
            function __() { this.constructor = d; }
            d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
        };
    })();
    // Create and register a custom control.
    function customizeToolbox(s, e, shortTypeName, fullTypeName) {
        // Get info objects which are common for most controls.
        // Info objects which are unnecessary for the current implementation are commented out.
        var controlsFactory = e.ControlsFactory;
        var labelInfo = controlsFactory.getControlInfo("XRLabel");
        //var textInfo = controlsFactory.getPropertyInfo("XRLabel", "Text");
        //var stringInfo = controlsFactory.getPropertyInfo("XRLabel", "Text");
        //var objectEditor = controlsFactory.getPropertyInfo("XRLabel", "Size").editor;
        var numberInfo = controlsFactory.getPropertyInfo("XRLabel", "Angle");
    
        var customNumberSerializationInfo = $.extend({}, numberInfo, {
            propertyName: "Number",
            modelName: "@Number",
            displayName: "Number",
            defaultVal: 0,
            localizationId: ""
        }
        );
    
        // Create the NumericLabel surface.
        var NumericLabelSurface = (function (_super) {
            __extends(NumericLabelSurface, _super);
            function NumericLabelSurface(control, context) {
                _super.call(this, control, context);
                this.contenttemplate = "numeric-label-content";
                this.displaySomeProperty = ko.computed(function () {
                    var text = control["Number"] && control["Number"]();
                    return text ? text : (control["text"] && control["text"]() || "");
                });
            }
            return NumericLabelSurface;
        })(labelInfo.surfaceType);
    
        // Create an object with information about the NumericLabel toolbox item.
        var numericLabelInfo = controlsFactory.inheritControl("XRLabel", {
            surfaceType: NumericLabelSurface,
            defaultVal: {
                "@ControlType": fullTypeName,
                "@SizeF": "200,50"
            },
            toolboxIndex: 1,
            displayName: "Number",
            info: [customNumberSerializationInfo],
            popularProperties: ["Number"]
        });
    
        // Register the NumericLabel in the Report Designer Toolbox.
        controlsFactory.registerControl(shortTypeName, numericLabelInfo);
    
        // Add the "Number" property to the Property panel's "Expressions" tab.
        var defaultExpression = controlsFactory.getPropertyInfo(shortTypeName, "Expression")
        defaultExpression.expressionName = "Number"
        // Specify the event in which the property should be available.
        controlsFactory.setExpressionBinding(shortTypeName, "Number", controlsFactory._beforePrintPrintOnPage);
        // Add the "Number" property to the Property panel's "Data Bindings" section.
        var dataBindings = controlsFactory.getPropertyInfo(shortTypeName, "Data Bindings");
        dataBindings.allDataBindings.push("Number");
        // Specify the default data binding property.
        var defaultBinding = controlsFactory.getPropertyInfo(shortTypeName, "Data Binding");
        defaultBinding.bindingName = "Number";
        // Add the "Number" property to the Property Grid's Data category.
        s.AddToPropertyGrid("Data", customNumberSerializationInfo);
    }
    
  6. Add the numeric-label.js script file and resources to the View. Handle the client-side CustomizeToolbox event:

    @*A style that specifies the toolbox item icon.*@
    <link rel="stylesheet" href="~/css/numeric-label.css" />
    
    @*A template used to display the NumericLabel control on the Designer surface.*@
    <template id='numeric-label-content'>
        <div data-bind="styleunit: { lineHeight: contentSizes().height / _context.zoom() }" style="box-sizing: border-box;
                                    letter-spacing: normal; width: 100%">
            <div class="dxrd-control-content" data-bind="text: displaySomeProperty, style: contentCss"></div>
        </div>
    </template>
    
    @*The code that creates and registers the NumericLabel control.*@
    <script src="~/js/numeric-label.js"></script>
    
    
    @{
        var designerRender = Html.DevExpress().ReportDesigner("reportDesigner")
            .Height("1000px")
            .ClientSideEvents(configure => configure.CustomizeToolbox("onCustomizeToolbox"))
            .Bind("TestReport");
        @designerRender.RenderHtml();
    
        //Get the NumericLabel control's type name.
        string shortTypeName = typeof(NumericLabel).FullName;
        string fullTypeName = typeof(NumericLabel).AssemblyQualifiedName;
    }
    
    <script type="text/javascript" id="script">
        function onCustomizeToolbox(s, e) {
            customizeToolbox(s, e, '@shortTypeName', '@fullTypeName');
            // Hide the Text property in the NumericLabel control's Property panel.
            s.GetPropertyInfo('@shortTypeName', "Text").visible = false;
            // Hide the XRLabel control in the Toolbox.
            var info = e.ControlsFactory.getControlInfo("XRLabel");
            info.isToolboxItem = false;
        }
    </script>
    

Use LibMan to Manage Client-Side Libraries

Right-click the project in the Solution Explorer and select Manage Client-Side Libraries to open the libman.json file.

Manage Client-Side Libraries

Paste the following content and save the file:

{
"version": "1.0",
"defaultProvider": "filesystem",
"libraries": [
    {
    "library": "node_modules/devextreme/dist/css/icons/",
    "destination": "wwwroot/css/icons",
    "files": [
        "dxicons.ttf",
        "dxicons.woff2",
        "dxicons.woff"
    ]
    },
    {
    "library": "NumericLabel/css/",
    "destination": "wwwroot/css/",
    "files": [
        "numeric-label.css",
        "NumericLabel.png"
    ]
    },
    {
    "library": "NumericLabel/js/",
    "destination": "wwwroot/js/",
    "files": [
        "numeric-label.js"
    ]
    }
]
}

Note

If your application already uses libraries listed above, remove duplicate library references to ensure they are registered only once.

For more information on LibMan, review the following article: Use LibMan with ASP.NET Core in Visual Studio.

Remove an Existing Control from the Toolbox

You can use the CustomizeToolbox event to remove an existing control from the Toolbox. Call the getControlInfo method of the event argument’s ASPxClientReportDesignerCustomizeToolboxEventArgs.ControlsFactory property to obtain the specified control and set the IElementMetadata.isToolboxItem property to false:

function onCustomizeToolbox(s, e) {
    // Remove the Label toolbox item.
    var info = e.ControlsFactory.getControlInfo("XRLabel");
    info.isToolboxItem = false;
}

Run the Application

Run the application to invoke the End-User Designer. Create a new report, and drop the NumericLabel control from the Toolbox to the design surface:

See Also