Skip to main content
All docs
V24.1

Custom Functions

  • 6 minutes to read

Overview

If you build an Expression, you can use functions. DevExpress Reports ship with a number of predefined functions that address common user scenarios. You can also implement and register custom functions. This topic explain how you can do that. In essence, you need to create a class the implements certain interfaces. The scope of your custom function then depends on the interfaces you implemented, on the attributes you applied to the class, and on the registration method you chose.

For information on custom aggregate functions, review the following help topic: Custom Aggregate Functions.

Custom Function Interfaces

To create a custom function, define a class that implements one or more of the following interfaces:

ICustomFunctionOperator
Declares the base functionality for custom functions.
ICustomFunctionOperatorBrowsable
Contains descriptive information about a custom function for use in the Expression editor (category, description, number of parameters).
ICustomFunctionOperatorFormattable
Allows you to use the Query Builder or filter editor to insert a string into SQL queries generated for SELECT operations.
ICustomFunctionDisplayAttributes
Allows you to create a custom function displayed as a comparison operator and specify the operator’s display settings.

Registration Scope

You should register custom functions in your Reporting application. When you register a function, you can choose between two scopes in which the function is available:

Data Access Scope

  • Query Builder
    • Expression Editor
    • FilterString Editor
  • Data Wizard

Reporting Scope

Registration Methods

Visual Studio Report Designer

Place an attribute on a custom function to enable it in the Visual Studio Report Designer. Use the following attribute:

VSDesignerCustomFunctionAttribute
Registers a custom function in the Visual Studio Report Designer. You can specify the VSDesignerCustomFunctionScope attribute argument to define the registration scope in the Visual Studio Report Designer.
using DevExpress.XtraReports.Design;
using DevExpress.XtraReports.Expressions;
// ...
    [VSDesignerCustomFunction]
    public class MakeDate : ReportCustomFunctionOperatorBase {
    // ...
    }
    // ...
    [VSDesignerCustomFunction(VSDesignerCustomFunctionScope.Reports)]
    public class ReportCustomFunctionOperator : ReportCustomFunctionOperatorBase {
    // ...
    }
    // ...
    [VSDesignerCustomFunction]
    public class CustomFunctionInQuery : ICustomFunctionOperatorFormattable, ICustomFunctionOperatorBrowsable {
    // ...
    }

End User Report Designer

At runtime use one of the following methods:

CriteriaOperator.RegisterCustomFunction
Registers the function so that it can be accessed anywhere in the application. The available scopes are Data Access and Reporting.
CustomFunctions.Register
Registers a function so that it is only available in the Reporting scope.
using DevExpress.Data.Filtering;
using DevExpress.XtraReports.Expressions;
// ...
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();

            CriteriaOperator.RegisterCustomFunction(new CustomFunctionInQuery());
            CustomFunctions.Register(new MakeDate());
        }
        // ...
    }

Example: Implement a Function

Implementation

To add a custom function, create a ReportCustomFunctionOperatorBase class descendant.

The following code defines the MakeDate(int year, int month, int day) custom function in the new Date & Time category:

using DevExpress.Data.Filtering;
using DevExpress.Xpo.DB;
using DevExpress.XtraReports.Design;
using DevExpress.XtraReports.Expressions;
using System;
using System.Linq;
// ...
    [VSDesignerCustomFunction]
    public class MakeDate : ReportCustomFunctionOperatorBase {
        public override string FunctionCategory => "Date & Time";
        public override int MinOperandCount => 3;
        public override int MaxOperandCount => 3;
        public override object Evaluate(params object[] operands) {
            var ints = operands.Cast<int>().ToArray();
            return new DateTime(ints[0], ints[1], ints[2]);
        }
        public override bool IsValidOperandType(int operandIndex, int operandCount, Type type) {
            if (operandIndex >= operandCount)
                return false;
            return type == typeof(int);
        }
        public override string Description => "MakeDate(int year, int month, int day)\r\nCreates Datetime instance based on passed year, month, day values";

        public override string Name => "MakeDate";
    }

Registration

Register in Visual Studio Report Designer

The VSDesignerCustomFunction attribute without arguments enables the function globally in Visual Studio Report Designer, that is, the function is available in the Data Access and Reporting scopes.

Register at Runtime

Call the CustomFunctions.Register static method at application startup:

using DevExpress.XtraReports.Expressions;
// ...
    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();

// ...
            CustomFunctions.Register(new MakeDate());
        }
        // ...
    }

After registration, the function is available in the Expression Editor and expression bindings at runtime.

Unregister a Function

To unregister a previously registered function, call the CustomFunctions.Unregister static method.

Unregistered functions are not available in the Expression Editor. An expression that has unregistered functions is evaluated as an empty value.

Invoke the Expression Editor

The Expression Editor displays the MakeDate function in the Date & Time category:

Custom Function in Expression Editor for WinForms

Custom Functions in Web Applications

If you develop a web application, review the following help topics for more information: