Skip to main content
All docs
V23.2

A Custom Editor for a Custom Parameter Type

  • 4 minutes to read

This topic explains how to implement a custom parameter type, add custom type parameters to a report, and create a custom editor for the Document Viewer Parameters Panel. The custom parameter type defines email addresses.

View Example

Create a Custom Parameter Type and a Converter

Define a CustomParameterType class with the Value property. Implement a CustomParameterTypeConverter converter to display a parameter value in a document.

using System;
using System.ComponentModel;
using System.Globalization;

    [TypeConverter(typeof(CustomParameterTypeConverter))]
    public class CustomParameterType
    {
        public string Value { get; set; }
        public override string ToString()
        {
            return Value;
        }
    }

    public class CustomParameterTypeConverter : TypeConverter
    {
        public override object ConvertTo(ITypeDescriptorContext context,
            CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(string))
            {
                return ((CustomParameterType)value).Value;
            }
            return base.ConvertTo(context, culture, value, destinationType);
        }
        public override bool CanConvertTo(ITypeDescriptorContext context,
            Type destinationType)
        {
            return destinationType == typeof(string) ||
                base.CanConvertTo(context, destinationType);
        }

        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
        }
        public override object ConvertFrom(ITypeDescriptorContext context,
            CultureInfo culture, object value)
        {
            var valueString = value as string;
            if (valueString != null)
            {
                return new CustomParameterType { Value = valueString };
            }
            return base.ConvertFrom(context, culture, value);
        }
    }

Implement a Custom Parameter Serializer

A serializer is necessary to pass data from the client to the controller on the server and store the parameter value in report definition files.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using CustomParameterEditorAngularExample;
using DevExpress.XtraReports.Native;

namespace CustomParameterEditorAngularExample
{
    [TypeConverter(typeof(CustomParameterTypeConverter))]
    public class CustomDataSerializer : IDataSerializer
    {
        public const string Name = "myCustomDataSerializer";

        public bool CanDeserialize(string value, string typeName, object extensionProvider)
        {
            return typeName == typeof(CustomParameterType).FullName;
        }

        public bool CanSerialize(object data, object extensionProvider)
        {
            return data is CustomParameterType;
        }

        public object Deserialize(string value, string typeName, object extensionProvider)
        {
            if (typeName == typeof(CustomParameterType).FullName)
            {
                return new CustomParameterType { Value = value };
            }
            return null;
        }

        public string Serialize(object data, object extensionProvider)
        {
            var parameter = data as CustomParameterType;
            return parameter != null ? parameter.Value : null;
        }
    }
}

Register Custom Classes and Serializer at Startup

Add the following code snippet to the Program.cs file to register the CustomParameterType, an array of CustomParameterType, and the CustomDataSerializer service in the application:

DevExpress.Utils.DeserializationSettings.RegisterTrustedClass(typeof(CustomParameterType));
DevExpress.Utils.DeserializationSettings.RegisterTrustedClass(typeof(CustomParameterType[]));
SerializationService.RegisterSerializer(CustomDataSerializer.Name, new CustomDataSerializer());

For more information, review the following help topic: Reporting — Safe Deserialization.

Specify an Editor Template in a CustomizeParameterEditors Callback

In the CustomizeParameterEditors callback function, specify the name of the template that contains the custom editor (custom-parameter-text-editor). The editor implements the email validation rule. For more information on validation rules, review the following help topic: Validator Validation Rules.

<dx-report-viewer [reportUrl]="reportUrl" height="calc(100vh - 90px)" developmentMode="true">
    <dxrv-request-options [invokeAction]="invokeAction" [host]="hostUrl"></dxrv-request-options>
    <dxrv-progressbar-settings position="BottomLeft"></dxrv-progressbar-settings>
    <dxrv-callbacks (CustomizeParameterEditors)="onCustomizeParameterEditors($event)"></dxrv-callbacks>
</dx-report-viewer>
import { Component, Inject, ViewEncapsulation } from '@angular/core';

@Component({
    selector: 'report-viewer',
    encapsulation: ViewEncapsulation.None,
    templateUrl: './report-viewer.html',
    styleUrls: [
        "../../../node_modules/devextreme/dist/css/dx.material.blue.light.css",
        "../../../node_modules/@devexpress/analytics-core/dist/css/dx-analytics.common.css",
        "../../../node_modules/@devexpress/analytics-core/dist/css/dx-analytics.material.blue.light.css",
        "../../../node_modules/devexpress-reporting/dist/css/dx-webdocumentviewer.css"
    ]
})
export class ReportViewerComponent {
    reportUrl: string = "CustomParameterReport";
    invokeAction: string = '/DXXRDV';

    onCustomizeParameterEditors(event): void {
        const parameter = event.args.parameter;
        const info = event.args.info;
        if (parameter.type === 'CustomParameterType') {
                info.validationRules = info.validationRules || [];
                info.validationRules.push(
                    { type: 'email', message: 'Email parameter value has invalid format.' });
                info.editor.header = "custom-parameter-text-editor";
        }
    }

    constructor(@Inject('BASE_URL') public hostUrl: string) { }
}

Register Editor Template

The custom-parameter-text-editor template is registered as the myCustomInput component in app.component files:

<ng-template #myCustomInput let-data="data">
    <custom-input-component [data]="data"></custom-input-component>
</ng-template>
import { AfterViewInit, Component, TemplateRef, ViewChild } from '@angular/core';
import { TemplateEngine } from 'devexpress-reporting-angular/dx-report-viewer';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html'
})
export class AppComponent implements AfterViewInit {
    title = 'report-viewer-app';
    @ViewChild('myCustomInput') myCustomInput!: TemplateRef<{ data: any }>;
    constructor(private _templateEngine: TemplateEngine) {
    }
    ngAfterViewInit(): void {
        this._templateEngine.register('custom-parameter-text-editor', this.myCustomInput);
    }
}

The myCustomInput component is a DevExtreme text editor defined as follows:

<dx-text-box [value]="data.value" [disabled]="data.disabled">
    <dx-validator [validationRules]="data.validationRules">
    </dx-validator>
</dx-text-box>
import { Component, Input, OnInit } from '@angular/core';
import { IEditorViewModel } from '@devexpress/analytics-core/analytics-widgets-native';

@Component({
    selector: 'custom-input-component',
    templateUrl: 'custom.input.component.html'
})
export class CustomInputComponent {
    @Input('data') data!: IEditorViewModel;
}

For more information about the DevExtreme text editor, review the following help topic: dxTextBox.

You should add related modules to the app.module.ts file:

import { DxTextBoxModule } from "devextreme-angular";
import { DxValidatorModule } from "devextreme-angular";

import { CustomInputComponent } from './custominputcomponent/custom.input.component';

@NgModule({
    declarations: [
    // ...
        CustomInputComponent,
    ],
    imports: [
    // ...
        DxTextBoxModule,
        DxValidatorModule
    ],
    providers: [],
    bootstrap: [AppComponent]
})
export class AppModule { }

Add Custom Parameter to Report

The following code snippet adds a CustomParameterType parameter to the report and binds it to the label2 XRLabel control:

using DevExpress.XtraReports.Parameters;
using DevExpress.XtraReports.UI;
// ...
            Parameter customMailParameter = new Parameter {
                Description = "Custom Email Parameter",
                Name = "customMailParameter",
                ValueInfo = "SampleMail@example.com",
                Type = typeof(CustomParameterType),
                Visible = true,
                Enabled = true
            };

            this.Parameters.Add(customMailParameter);

            this.label2.ExpressionBindings.AddRange(new ExpressionBinding[] {
            new ExpressionBinding("BeforePrint", "Text", "?customMailParameter") });

Run the App to Show the Result

The Document Viewer control that displays a report with a custom parameter appears as follows:

Angular Custom Parameter Editor