Skip to main content

DevExpress v25.1 Update — Your Feedback Matters

Our What's New in v25.1 webpage includes product-specific surveys. Your response to our survey questions will help us measure product satisfaction for features released in this major update and help us refine our plans for our next major release.

Take the survey Not interested

DxGrid.CustomValidators Property

Allows you to declare custom validator components.

Namespace: DevExpress.Blazor

Assembly: DevExpress.Blazor.v25.1.dll

NuGet Package: DevExpress.Blazor

#Declaration

C#
[Parameter]
public RenderFragment CustomValidators { get; set; }

#Property Value

Type Description
RenderFragment

A template (render fragment) that allows you to declare custom validators.

#Remarks

The Grid uses the DataAnnotationsValidator to validate user input based on data annotation attributes defined in an edit model.

You can also create custom validator components as described in the following Microsoft topic: Validator components. To enable custom validation in the Grid, declare validator components in the CustomValidators template.

Note that the declared custom validators override the standard DataAnnotationsValidator. If you need to use DataAnnotationsValidator in addition to the custom validators, declare it in the CustomValidators template explicitly.

For more information about validation in the Grid, refer to the following topic: Validate User Input.

The following code snippet uses the custom validator to check the Title field value.

#Model-Level Errors

The following example uses a custom validator to evaluate the Title field value.

View Example: Custom Validation View Example: Display an error message from the Web API Service

@page "/"

@using CustomValidation.Models
@using Microsoft.EntityFrameworkCore
@inject IDbContextFactory<NorthwindContext> NorthwindContextFactory
@implements IDisposable

<DxGrid Data="GridDataSource"
        EditModelSaving="OnEditModelSaving"
        CustomizeDataRowEditor="OnCustomizeDataRowEditor"
        CustomizeEditModel="OnCustomizeEditModel"
        KeyFieldName="EmployeeId">
    <Columns>
        <DxGridCommandColumn DeleteButtonVisible="false" />
        <DxGridDataColumn FieldName="FirstName" />
        <DxGridDataColumn FieldName="LastName" />
        <DxGridDataColumn FieldName="Title" />
        <DxGridDataColumn FieldName="HireDate" />
    </Columns>
    <EditFormTemplate Context="editFormContext">
        <DxFormLayout>
            <DxFormLayoutItem Caption="First Name:">
                @editFormContext.GetEditor("FirstName")
            </DxFormLayoutItem>
            <DxFormLayoutItem Caption="Last Name:">
                @editFormContext.GetEditor("LastName")
            </DxFormLayoutItem>
            <DxFormLayoutItem Caption="Title:">
                @editFormContext.GetEditor("Title")
            </DxFormLayoutItem>
            <DxFormLayoutItem Caption="Hire Date:">
                @editFormContext.GetEditor("HireDate")
            </DxFormLayoutItem>
        </DxFormLayout>
    </EditFormTemplate>
    <CustomValidators>
        <MyCustomValidator DataItemValidating="ValidateGridData" />
    </CustomValidators>
</DxGrid>

@code {
    IEnumerable<object> GridDataSource { get; set; }
    NorthwindContext Northwind { get; set; }

    void ValidateGridData(ValidationMessageStoreEventArgs e) {
        var employee = (Employee)e.EditModel;
        if (employee.Title == null || !employee.Title.Contains("Sales")) {
            e.AddError(nameof(employee.Title), "The Title field value should contain 'Sales'.");
        }
    }

    protected override async Task OnInitializedAsync() {
        Northwind = NorthwindContextFactory.CreateDbContext();
        GridDataSource = await Northwind.Employees.ToListAsync();
    }

    void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e) {
        if(e.IsNew) {
            var editModel = (Employee)e.EditModel;
            editModel.EmployeeId = GridDataSource.Count() + 1;
        }
    }

    async Task OnEditModelSaving(GridEditModelSavingEventArgs e) {
        var editModel = (Employee)e.EditModel;
        if (e.IsNew)
            await Northwind.AddAsync(editModel);
        else
            e.CopyChangesToDataItem();
        await Northwind.SaveChangesAsync();
        GridDataSource = await Northwind.Employees.ToListAsync();
    }

    void OnCustomizeDataRowEditor(GridCustomizeDataRowEditorEventArgs e) {
        if(e.EditSettings is ITextEditSettings settings)
            settings.ShowValidationIcon = true;
    }

    public void Dispose() {
        Northwind?.Dispose();
    }
}

Blazor Grid Editing Custom Validation

#Database-Level Errors

In the following example, the bound database throws an error if a new row’s Field Name is set to Test. A custom validator catches this error and displays the error message in the Grid:

@page "/"

@using CustomValidation.Models
@using Microsoft.EntityFrameworkCore
@using System.ComponentModel.DataAnnotations
@inject IDbContextFactory<NorthwindContext> NorthwindContextFactory
@implements IDisposable

<DxGrid Data="GridDataSource"
        EditModelSaving="OnEditModelSaving"
        EditMode="GridEditMode.EditRow"
        CustomizeDataRowEditor="OnCustomizeDataRowEditor"
        CustomizeEditModel="OnCustomizeEditModel"
        KeyFieldName="EmployeeId">
    <Columns>
        <DxGridCommandColumn DeleteButtonVisible="false" />
        <DxGridDataColumn FieldName="FirstName" />
        <DxGridDataColumn FieldName="LastName" />
        <DxGridDataColumn FieldName="Title" />
        <DxGridDataColumn FieldName="HireDate" />
    </Columns>
    <CustomValidators>
        <MyCustomValidator @ref="MyValidator" />
    </CustomValidators>
</DxGrid>

@code {
    MyCustomValidator MyValidator { get; set; }
    IEnumerable<object> GridDataSource { get; set; }
    NorthwindContext Northwind { get; set; }

    protected override async Task OnInitializedAsync() {
        Northwind = NorthwindContextFactory.CreateDbContext();
        Northwind.EnsureEmployeeFirstNameTriggerExists();
        GridDataSource = await Northwind.Employees.ToListAsync();
    }

    void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e) {
        if(e.IsNew) {
            var editModel = (Employee)e.EditModel;
            editModel.EmployeeId = GridDataSource.Count() + 1;
        }
    }

    async Task OnEditModelSaving(GridEditModelSavingEventArgs e) {
        var editModel = (Employee)e.EditModel;
        if (e.IsNew)
            await Northwind.AddAsync(editModel);
        else
            e.CopyChangesToDataItem();
        try {
            await Northwind.SaveChangesAsync();
            GridDataSource = await Northwind.Employees.ToListAsync();
        }
        catch (DbUpdateException ex) {
            MyValidator?.ClearErrors();
            var errors = new Dictionary<string, List<string>>();
            errors.Add(nameof(editModel.FirstName), [ex.GetBaseException().Message]);
            MyValidator?.DisplayErrors(errors);
            e.Cancel = true;
        }
    }

    void OnCustomizeDataRowEditor(GridCustomizeDataRowEditorEventArgs e) {
        if(e.EditSettings is ITextEditSettings settings)
            settings.ShowValidationIcon = true;
    }

    public void Dispose() {
        Northwind?.Dispose();
    }
}

Blazor Grid Editing - Database Error Catching

#Implements

See Also