Create and Register a Custom Control in 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 .

View Example: Custom Report Control in the Web End User Designer Toolbox

Prerequisites

Start with an existing Web Reporting application or create a new application as described in the following help topics:

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 introduce a new property:

    using DevExpress.Utils.Serializing;
    using DevExpress.XtraReports.UI;
    using System.ComponentModel;
    namespace YourAppNamespace
    {
        public class CustomLabel : XRLabel {
            [Browsable(true), Bindable(false), Category("Data")]
            [XtraSerializableProperty]
            [DefaultValue("")]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
            EditorBrowsable(EditorBrowsableState.Always)]
            public string CustomNumber { get; set; }
        }
    }
    
  2. Add a bindable property to the CustomLabel class as shown below. Mark this property with the Bindable attribute set to true. Override the PutStateToBrick protected method to assign the bindable property value to the VisualBrick.Text property:

            [Browsable(true), Bindable(true), Category("Data")]
            [XtraSerializableProperty]
            [DefaultValue("")]
            [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible),
            EditorBrowsable(EditorBrowsableState.Always)]
            public string StringData { get; set; }
    
            protected override void PutStateToBrick(DevExpress.XtraPrinting.VisualBrick brick, DevExpress.XtraPrinting.PrintingSystemBase ps) {
                base.PutStateToBrick(brick, ps);
                brick.Text = StringData ?? CustomNumber;
            }
    
  3. Rebuild the project. The CustomLabel control appears in the Visual Studio Report Designer 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 CustomLabel folder to the project.
  2. Add a control's icon to the 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 folder with the following content:

    .dxrd-image-yournamespace_customlabel {
        background-image: url(custom-label.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 custom-label.js file to the CustomLabel 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 __());
        };
    })();
    
    function customizeToolbox(s, e, shortTypeName, fullTypeName) {
    
        // Obtain standard label information.
        var controlsFactory = e.ControlsFactory;
        var labelInfo = controlsFactory.getControlInfo("XRLabel");
        var stringInfo = controlsFactory.getPropertyInfo("XRLabel", "Text");
        var objectEditor = controlsFactory.getPropertyInfo("XRLabel", "Size").editor;
        var numberInfo = controlsFactory.getPropertyInfo("XRLabel", "Angle");
    
        // Create serialization information for the custom properties.
        var addressSerializationInfos = [
            $.extend({}, stringInfo, { 
                propertyName: "countryCode", 
                modelName: "@CountryCode", 
                displayName: "CountryCode", 
                localizationId: "" }),
            $.extend({}, stringInfo, { 
                propertyName: "city", 
                modelName: "@City", 
                displayName: "City", 
                localizationId: "" }),
        ];
    
        var customerSerializationInfo = {
            propertyName: "customerInfo", 
            modelName: "customerInfo", 
            displayName: "Customer Information", 
            defaultVal: "", localizationId: "",
            editor: objectEditor, info: addressSerializationInfos
        }
    
        var customNumberSerializationInfo = $.extend({}, numberInfo,{ 
            propertyName: "customNumber", 
            modelName: "@CustomNumber", 
            displayName: "Custom Number", 
            defaultVal: null, 
            localizationId: "" }
        );
    
        var bindablePropertySerializationInfo = $.extend({}, stringInfo, {
            propertyName: "stringData", 
            modelName: "@StringData", 
            displayName: "Bindable Property", 
            defaultVal: "", 
            localizationId: ""
        });
    
        // Create the custom label surface.
        var CustomLabelSurface = (function (_super) {
            __extends(CustomLabelSurface, _super);
            function CustomLabelSurface(control, context) {
                _super.call(this, control, context);
                this.contenttemplate = "custom-label-content";
                this.displaySomeProperty = ko.computed(function () {
                    var text = control["customNumber"] && control["customNumber"]();
                    return text ? text : (control["text"] && control["text"]() || "");
                });
            }
            return CustomLabelSurface;
        })(labelInfo.surfaceType);
    
        // Create an object with information about the CustomLabel toolbox item.
        var customLabelInfo = controlsFactory.inheritControl("XRLabel", {
            surfaceType: CustomLabelSurface,
            defaultVal: {
                "@ControlType": fullTypeName,
                "@SizeF": "400,50"
            },
            toolboxIndex: 1,
            info: [customerSerializationInfo, bindablePropertySerializationInfo, customNumberSerializationInfo],
            popularProperties: ["customerInfo", "stringData", "customNumber"],
        });
    
        // Register the custom label in the Report Designer Toolbox.
        controlsFactory.registerControl(shortTypeName, customLabelInfo);
    
        // Adjust the custom label bindings.
        var defaultExpression = controlsFactory.getPropertyInfo(shortTypeName, "Expression")
        defaultExpression.expressionName = "StringData"
        controlsFactory.setExpressionBinding(shortTypeName, "StringData", controlsFactory._beforePrintPrintOnPage);
    
        var dataBindings = controlsFactory.getPropertyInfo(shortTypeName, "Data Bindings");
        dataBindings.allDataBindings.push("StringData");
        var defaultBinding = controlsFactory.getPropertyInfo(shortTypeName, "Data Binding");
        defaultBinding.bindingName = "StringData";
    
        // Add custom properties to the Property Grid's Data category.
        s.AddToPropertyGrid("Data", customerSerializationInfo);
        s.AddToPropertyGrid("Data", customNumberSerializationInfo);
    }
    
  1. Add the custom-label.js script file to the page and handle the client-side ASPxClientReportDesigner.CustomizeToolbox event:

    NOTE

    You may need to add the @Import directive to specify the CustomLabel class namespace.

    <%@Import Namespace="YourAppNamespace"%>
    
    <asp:Content ID="Content" ContentPlaceHolderID="MainContent" runat="server">
        <script type="text/javascript">
            function onCustomizeToolbox(s, e) {
                customizeToolbox(s, e, "<%= typeof(CustomLabel).ToString() %>",
                        "<%= typeof(CustomLabel).AssemblyQualifiedName %>");
            }
        </script>
        <dx:ASPxReportDesigner EnableRichTextEditor="False" ID="ASPxReportDesigner1" runat="server">
            <ClientSideEvents CustomizeToolbox="onCustomizeToolbox" />
        </dx:ASPxReportDesigner>
    </asp:Content>
    
  2. Add resources and libraries to the page:

    <asp:Content ID="Content" ContentPlaceHolderID="MainContent" runat="server">
    ...
    <link href="CustomLabel\custom-label.css" rel="stylesheet" />
    <!-- #include file = "CustomLabel\custom-label-content.html" -->
    ...
        </asp:Content>
    

Remove an Existing Control from the Toolbox

You can use the CustomizeToolbox event to remove an existing control from the Toolbox. Use 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 labelInfo = e.ControlsFactory.getControlInfo("XRLabel");
    labelInfo.isToolboxItem = false;
}

Bind the Custom Control to the Report Parameter

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

Open the Field List and add a new report parameter with default settings:

Switch to the Expressions tab and click the ellipsis button in the StringData field to invoke the Expression Editor. Insert the report's parameter:

The StringData custom property is bound to the report parameter. The user can set the parameter in the Designer's Preview or in the Document Viewer to change the StringData property of the CustomLabel control.

See Also