Back to Devexpress

Cell Editors in Blazor Grid

blazor-404780-components-grid-editing-and-validation-cell-editors.md

latest12.3 KB
Original Source

Cell Editors in Blazor Grid

  • Jan 20, 2026
  • 5 minutes to read

The Grid component generates and configures cell editors for individual columns based on associated data types. The component displays these cell editors in the filter row and edit cells. You can display an automatically generated column editor in the edit or pop-up edit form.

This topic describes how to customize cell editors displayed during edit operations. For additional information about filter row cell editors, refer to the following help topics:

Configure Cell Editors

You can declare an object that contains editor settings in the DxGridDataColumn.EditSettings property to customize the default editor or replace it with another editor. If the editor does not support the associated data type, the Grid uses a read-only text box instead. The table below lists classes that define cell editor settings and the corresponding data types:

|

Editor Settings

|

Generated for Data Types

|

Supported Data Types

| | --- | --- | --- | |

DxCheckBoxSettings

|

Boolean

|

All data types

| |

DxComboBoxSettings

|

Enum

|

All data types

| |

DxDateEditSettings

|

DateOnly, DateTime, DateTimeOffset

|

DateOnly, DateTime, DateTimeOffset

| |

DxMaskedInputSettings

|

Never generated

|

Numeric, String, TimeSpan, TimeOnly,
DateTime, DateOnly, DateTimeOffset

| |

DxMemoSettings

|

Never generated

|

String

| |

DxSpinEditSettings

|

Numeric

|

Numeric

| |

DxTextBoxSettings

|

String

|

String

| |

DxTimeEditSettings

|

TimeOnly

|

TimeOnly, TimeSpan, DateTime

|

The following code snippet customizes settings of an automatically generated spin editor:

razor
<DxGrid Data="@products" ShowFilterRow="true" EditMode="GridEditMode.EditRow">
    <Columns>
        <DxGridCommandColumn />
        <DxGridDataColumn FieldName="ProductID" >
            <EditSettings>
                <DxSpinEditSettings ShowSpinButtons="false" ReadOnly="true" NullText="Type the ID" />
            </EditSettings>
        </DxGridDataColumn>
        <DxGridDataColumn FieldName="ProductName" />
        <DxGridDataColumn FieldName="UnitPrice" />
        <DxGridDataColumn FieldName="UnitsInOrder" />
    </Columns>
</DxGrid>

At runtime, handle the CustomizeDataRowEditor event to customize a data row editor separately from the filter row editor. Call the GetColumnEditSettings method to access and customize editor settings.

Cell Edit Template

The column’s CellEditTemplate allows you to display custom content in the data column’s edit cell. To define a common cell edit template for all data columns, use the Grid’s DataColumnCellEditTemplate. Both templates include the context parameter that contains DataColumn and DataItem objects. The context’s Grid property allows you to access the Grid and its extensive API.

Note

When you place a templated component in the edit cell template, a Razor error may occur. To prevent this error, specify the Context parameter explicitly either for the Grid template or for the nested component.

The following code snippet displays a date editor with custom command buttons in an edit cell:

razor
@using Microsoft.EntityFrameworkCore
@inject IDbContextFactory<NorthwindContext> NorthwindContextFactory

<DxGrid @ref="Grid"
        Data="Data"
        KeyFieldName="EmployeeId"
        EditMode="GridEditMode.EditRow">
    <Columns>
        <DxGridCommandColumn />
        <DxGridDataColumn FieldName="FirstName" />
        <DxGridDataColumn FieldName="LastName" />
        <DxGridDataColumn FieldName="Title" />
        <DxGridDataColumn FieldName="HireDate">
            <CellEditTemplate>
                @{
                    var employee = (Employee)context.EditModel;
                }
                <DxDateEdit @bind-Date="@employee.HireDate">
                    <Buttons>
                        <DxEditorButton IconCssClass="editor-icon editor-icon-chevron-left-small"
                                        Tooltip="Previous date"
                                        Position="@EditorButtonPosition.Left"
                                        Click="@(_ => employee.HireDate = employee.HireDate?.AddDays(-1))" />
                        <DxEditorButton IconCssClass="editor-icon editor-icon-chevron-right-small"
                                        Tooltip="Next date"
                                        Position="@EditorButtonPosition.Right"
                                        Click="@(_ => employee.HireDate = employee.HireDate?.AddDays(1))" />
                    </Buttons>
                </DxDateEdit>
            </CellEditTemplate>
        </DxGridDataColumn>
    </Columns>
</DxGrid>

@code {
    IEnumerable<object> Data { get; set; }
    NorthwindContext Northwind { get; set; }
    DateTime DateTimeValue { get; set; } = DateTime.Today;
    bool CalendarVisible { get; set; }

    void OnChangeDayButtonClick(bool isAdd) {
        CalendarVisible = false;
        DateTimeValue = DateTimeValue.AddDays(isAdd ? 1 : -1);
    }
    // ...
}
csharp
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace Grid.Northwind {
    public partial class Employee {
        public int EmployeeId { get; set; }
        [Required]
        public string LastName { get; set; }
        [Required]
        public string FirstName { get; set; }
        [Required]
        public string Title { get; set; }
        public string TitleOfCourtesy { get; set; }
        public Nullable BirthDate { get; set; }
        [Required]
        [Range(typeof(DateTime), "1/1/2000", "1/1/2020",
        ErrorMessage = "HireDate must be between {1:d} and {2:d}")]
        public Nullable HireDate { get; set; }
        public string Address { get; set; }
        public string City { get; set; }
        public string Region { get; set; }
        public string PostalCode { get; set; }
        public string Country { get; set; }
        public string HomePhone { get; set; }
        public string Extension { get; set; }
        public byte[] Photo { get; set; }
        public string Notes { get; set; }
        public Nullable<int> ReportsTo { get; set; }
        public string PhotoPath { get; set; }
        public virtual ICollection<Order> Orders { get; set; }
        public string Text => $"{FirstName} {LastName} ({Title})";
        public string ImageFileName => $"Employees/{EmployeeId}.jpg";
    }
}
csharp
using Microsoft.EntityFrameworkCore;
#nullable disable

namespace Grid.Northwind {
    public partial class NorthwindContext : DbContext {

        public NorthwindContext(DbContextOptions<NorthwindContext> options)
            : base(options) {
        }
        // ...
        public virtual DbSet<Employee> Employees { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
            if(!optionsBuilder.IsConfigured) {
                optionsBuilder.UseSqlServer("Server=.\\sqlexpress;Database=Northwind;Integrated Security=true");
            }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder) {
            modelBuilder.HasAnnotation("Relational:Collation", "SQL_Latin1_General_CP1_CI_AS");
            // ...
            modelBuilder.Entity<Employee>(entity => {
                entity.HasIndex(e => e.EmployeeId, "EmployeeId");
                entity.HasIndex(e => e.LastName, "LastName");
                entity.HasIndex(e => e.FirstName, "FirstName");
                entity.HasIndex(e => e.Title, "Title");
                entity.HasIndex(e => e.BirthDate, "BirthDate");
                entity.HasIndex(e => e.HireDate, "HireDate");
                entity.HasIndex(e => e.Notes, "Notes");
            });
            OnModelCreatingPartial(modelBuilder);
        }

        partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
    }
}
csharp
using Microsoft.EntityFrameworkCore;
// ...
builder.Services.AddDbContextFactory<NorthwindContext>((sp, options) => {
    var env = sp.GetRequiredService<IWebHostEnvironment>();
    var dbPath = Path.Combine(env.ContentRootPath, "Northwind.mdf");
    options.UseSqlServer("Server=(localdb)\\MSSQLLocalDB;Integrated Security=true;AttachDbFileName=" + dbPath);
});
css
.editor-icon {
    width: 1rem;
    height: 1rem;
    background-size: contain;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    background-position: center center;
    background-color: currentColor;
    opacity: 0.7;
}

.editor-icon-chevron-right-small {
    -webkit-mask-image: url("../images/icons/chevron-right-small.svg");
    mask-image: url("../images/icons/chevron-right-small.svg");
}

.editor-icon-chevron-left-small {
    -webkit-mask-image: url("../images/icons/chevron-left-small.svg");
    mask-image: url("../images/icons/chevron-left-small.svg");
}

View Example: How to implement cascading combo boxes