Skip to main content
All docs
V24.2

Columns in Blazor Grid

  • 24 minutes to read

DevExpress Blazor Grid supports several column types: data column (bound and unbound), command column, and selection column. You can declare columns within the Columns template.

Watch Video: Grid - Column Types, Column Resize and Visibility

Column Types

The DevExpress Blazor Grid component supports the following column types:

Data column (Bound)

Bound columns get their data from the bound data source. Declare a DxGridDataColumn object in the Columns template and specify the FieldName property to bind the column to a data field.

DxGrid generates a user-friendly column caption based on the field name. Use the Caption property to specify a custom column name.

@inject WeatherForecastService ForecastService

<DxGrid Data="@Data">
    <Columns>
        <DxGridDataColumn FieldName="Date" DisplayFormat="D" />
        <DxGridDataColumn FieldName="TemperatureC" Caption="@("Temp. (\x2103)")" Width="120px" />
        <DxGridDataColumn FieldName="TemperatureF" Caption="@("Temp. (\x2109)")" Width="120px" />
        <DxGridDataColumn FieldName="Forecast" />
        <DxGridDataColumn FieldName="CloudCover" />
    </Columns>
</DxGrid>

@code {
    object Data { get; set; }

    protected override void OnInitialized() {
        Data = ForecastService.GetForecast();
    }
}

Blazor Grid Data Binding

Run Demo: Grid - Data Binding Read Tutorial: Bind Blazor Grid to Data

Create a Foreign Key (ComboBox) Column

A foreign key is a database key used to manage relationships between individual tables. You can use the key to identify a specific column in a referenced table and obtain column data. Do the following to create such a column:

  1. Add a DxGridDataColumn object to the Grid’s column collection.
  2. Assign the field name that stores foreign keys to the column’s FieldName property.
  3. Place DxComboBoxSettings in the column’s EditSettings tag.
  4. Assign an external data source to the Data setting.
  5. Assign the name of the external data source field that stores foreign keys to the ValueFieldName setting. The TextFieldName setting allows you specify text strings displayed within the Grid instead of foreign keys.

Combobox column

<DxGrid Data="Products"
        EditModelSaving="OnEditModelSaving"
        EditMode="GridEditMode.EditRow">
    <Columns>
        <DxGridCommandColumn DeleteButtonVisible="false" />
        <DxGridDataColumn FieldName="CategoryId" Caption="Category Name">
            <EditSettings>
                <DxComboBoxSettings
                    Data="Categories"
                    ValueFieldName="CategoryId"
                    TextFieldName="CategoryName"
                    FilteringMode="DataGridFilteringMode.Contains"
                    ClearButtonDisplayMode="DataEditorClearButtonDisplayMode.Auto"/>
            </EditSettings>
        </DxGridDataColumn>
        <DxGridDataColumn FieldName="ProductName" />
        <DxGridDataColumn FieldName="UnitPrice" DisplayFormat="c" />
        <DxGridDataColumn FieldName="UnitsInStock" />
        <DxGridDataColumn FieldName="QuantityPerUnit" />
    </Columns>
</DxGrid>

@code {
    NorthwindContext Northwind { get; set; }
    List<Product> Products { get; set; }
    List<Category> Categories { get; set; }
    @* ... *@
    async Task OnEditModelSaving(GridEditModelSavingEventArgs e) {  
        var editableProduct = (Product)e.EditModel;
        e.CopyChangesToDataItem();
        await Northwind.SaveChangesAsync();

        Products = await Northwind.Products.ToListAsync();
    }
    @* ... *@
}

View Example: Create a Foreign Key (ComboBox) Column

Data Column (Unbound)

Unbound columns display values that are not stored in the assigned data collection. To create an unbound column, declare a DxGridDataColumn object in the Columns template and specify the following properties:

UnboundType
Indicates that the column is unbound and specifies its data type.
FieldName
Specifies a unique name that should not match field names in the grid’s data source.

You can use one of the following APIs to populate an unbound column with data:

UnboundExpression
Specifies an expression that calculates column values. An expression can consist of field names, constants, operators, and functions and should use our Criteria Language Syntax.
UnboundColumnData
Allows you to implement custom logic or obtain column values from a custom/external data source.
<DxGrid Data="forecasts" UnboundColumnData="Grid_CustomUnboundColumnData">
    <Columns>
        <DxGridDataColumn FieldName="Date" Caption="Date" />
        <DxGridDataColumn FieldName="TemperatureC" Caption="@("Temperature (\x2103)")" />
        <DxGridDataColumn FieldName="TemperatureF" Caption="@("Temperature (\x2109)")"
                          UnboundType="GridUnboundColumnType.Decimal"
                          UnboundExpression="32 + [TemperatureC] / 0.5556" />
        <DxGridDataColumn FieldName="Summary"
                          UnboundType="GridUnboundColumnType.String" />
    </Columns>
</DxGrid>

@code {
    private WeatherForecast[]? forecasts;

    protected override async Task OnInitializedAsync() {
        forecasts = await ForecastService.GetForecastAsync(DateTime.Now);
    }

    void Grid_CustomUnboundColumnData(GridUnboundColumnDataEventArgs e) {
        if (e.FieldName == "Summary") {
            int temperature = Convert.ToInt32(e.GetRowValue("TemperatureC"));
            e.Value = GetTemperatureString(temperature);
        }
    }

    static string GetTemperatureString(int value) {
        if (value < -10)
            return "Cool";
        if (value >= -10 && value < 5)
            return "Chilly";
        if (value >= 5 && value < 15)
            return "Warm";
        return "Hot";
    }
}

DevExpress Blazor Grid - Unbound Columns

View Example: Create and Edit Unbound Columns

Run Demo: Unbound Columns

Limitations

Command Column

Declare a DxGridCommandColumn object in the Columns template to display a command column.

<DxGrid Data="Products" KeyFieldName="ProductId">
    <Columns>
        <DxGridCommandColumn />
        ...
    </Columns>
</DxGrid>

A command column displays CRUD-related buttons (New, Edit, and Delete) and the Clear button that resets values in the filter row. For rows in edit mode (EditRow), the column displays Save and Cancel buttons.

Blazor Grid Command Column

Run Demo: Edit Row Run Demo: Filter Row Read Tutorial: Edit Data in Blazor Grid

You can use the following properties to control the visibility of command buttons:

NewButtonVisible
Specifies whether the command column displays the New button.
EditButtonVisible
Specifies whether the command column displays Edit buttons.
DeleteButtonVisible
Specifies whether the command column displays Delete buttons.
ClearFilterButtonVisible
Specifies whether the command column displays the Clear button.
SaveButtonVisible
Specifies whether the command column displays the Save button in EditRow or EditCell edit mode.
CancelButtonVisible
Specifies whether the command column displays the Cancel button in EditRow or EditCell edit mode.

Selection Column

Declare a DxGridSelectionColumn object in the Columns template to display a selection column.

<DxGrid Data="Products" KeyFieldName="ProductId">
    <Columns>
        <DxGridSelectionColumn />
        ...
    </Columns>
</DxGrid>

When the SelectionMode property is set to Multiple (the default value), the selection column displays checkboxes. Users can click them to select and deselect individual rows.

Blazor Grid Selection Column Multiple Mode

In Multiple selection mode, the selection column displays the Select All checkbox in the column header. A user can click this checkbox to select or deselect all rows on the current page or on all grid pages depending on the SelectAllCheckboxMode property value. Available property values are as follows:

Page
The Select All checkbox selects and deselects all rows on the current grid page. This mode changes to Mixed when the Grid is bound to a large data source and vertical virtual scrolling mode is activated.
AllPages
The Select All checkbox selects and deselects all rows on all grid pages. This mode changes to Mixed when the Grid is bound to a large data source.
Mixed
The Select All checkbox selects and deselects all rows on the current grid page. An additional drop-down button displays a context menu that allows users to select and deselect all rows on all grid pages.
<DxGrid Data="Products" 
        KeyFieldName="ProductId" 
        SelectAllCheckboxMode="GridSelectAllCheckboxMode.Mixed">
    <Columns>...</Columns>
</DxGrid>

Blazor Grid Select All Checkbox

To hide the Select All checkbox, disable the column’s AllowSelectAll option.

Note

The Select All checkbox functionality has limitations. For more information, refer to the following section: Selection Limitations.

When the SelectionMode property is set to Single, the selection column displays radio buttons. Users can click a button to select one row at a time.

<DxGrid Data="Products" KeyFieldName="ProductId" SelectionMode="GridSelectionMode.Single">
    <Columns>
        <DxGridSelectionColumn />
        ...
    </Columns>
</DxGrid>

Blazor Grid Selection Column Single Mode

Run Demo: Selection Column Read Tutorial: Selection and Focus in Blazor Grid

Band Column (Header Bands)

You can combine columns into logical groups called bands. To create such a group, declare a DxGridBandColumn object and specify child columns in the Columns template. You can create as many nesting levels as your business task requires.

Multi-level headers

<DxGrid @ref="Grid"
        Data="Data">
    <Columns>
        <DxGridDataColumn FieldName="SalesPerson" Caption="Salesperson" />
        <DxGridBandColumn Caption="Order">
            <Columns>
                <DxGridDataColumn FieldName="CompanyName" />
                <DxGridDataColumn FieldName="OrderDate" Caption="Date" Width="100px" />
                <DxGridBandColumn Caption="Product">
                    <Columns>
                        <DxGridDataColumn FieldName="ProductName" Caption="Name" />
                        <DxGridDataColumn FieldName="UnitPrice" 
                                          DisplayFormat="c" 
                                          CaptionAlignment="GridTextAlignment.Right" 
                                          Width="100px" />
                    </Columns>
                </DxGridBandColumn>
                <DxGridDataColumn FieldName="Quantity" Width="80px" />
            </Columns>
        </DxGridBandColumn>
    </Columns>
</DxGrid>

@code {
    object Data { get; set; }
    IGrid Grid { get; set; }
    protected override async Task OnInitializedAsync() {
        var invoices = await NwindDataService.GetInvoicesAsync();
        var customers = await NwindDataService.GetCustomersAsync();
        Data = invoices.OrderBy(i => i.OrderDate).Join(customers, i => i.CustomerId, c => c.CustomerId, (i, c) => {
            return new {
                    CompanyName = c.CompanyName,
                    SalesPerson = i.Salesperson,
                    UnitPrice = i.UnitPrice,
                    OrderDate = i.OrderDate,
                    ProductName = i.ProductName,
                    Quantity = i.Quantity
            };
        });
    }
}

Run Demo: Grid - Header Bands

Column Settings

Column Order

The Grid layout can include multiple column zones. The display order of zones is as follows:

  1. Columns fixed to the left edge.
  2. Regular columns.
  3. Columns fixed to the right edge.

In a zone, the DxGrid displays columns based on their visible indices in the following order:

  1. Columns with non-negative visible indexes. The leftmost column has the smallest index value.

  2. Columns with unset and negative visible indexes. Columns appear in the same order as in grid markup.

Grouped columns are invisible unless you set the ShowGroupedColumns property to true.

Users can reorder columns by dragging headers within the column header panel or in the column chooser. Set the DxGrid.AllowColumnReorder or DxGridColumn.AllowReorder property to false to prevent users from reordering columns.

Column Width

DxGrid uses the fixed table layout algorithm to render HTML, and column widths never depend on the column content - the component does not adjust column width based on column content automatically. Refer to the following topic for more information about grid layout specifics: Layout Specifics.

You can use the following column properties to specify the grid column layout:

Width
Specifies the column’s width in CSS units.
MinWidth
Specifies a column’s minimum width in pixels.

Note that a non-empty band ignores these properties. The band width is the total width of nested column widths.

You can also call the AutoFitColumnWidths() method to adjust column widths to their content automatically. The following example calls the AutoFitColumnWidths method to calculate initial optimal column widths:

<DxGrid Data="Products"
        @ref="MyGrid"
        EditMode="GridEditMode.EditRow"
        TextWrapEnabled="false">
    <Columns>
        <DxGridCommandColumn MinWidth="135" />
        <DxGridDataColumn FieldName="ProductName" Width="20%" />
        <DxGridDataColumn FieldName="CategoryId" Caption="Category Name">
            <EditSettings>
                <DxComboBoxSettings Data="Categories" ValueFieldName="CategoryId" TextFieldName="CategoryName" />
            </EditSettings>
        </DxGridDataColumn>
        <DxGridDataColumn FieldName="Category.Description" Caption="Description" />
        <DxGridDataColumn FieldName="UnitPrice" DisplayFormat="c">
            <EditSettings>
                <DxSpinEditSettings MinValue="0M" Mask="n3" />
            </EditSettings>
        </DxGridDataColumn>
        <DxGridDataColumn FieldName="UnitsInStock" Width="50px" />
        <DxGridDataColumn FieldName="QuantityPerUnit" Width="50px" />
        <DxGridDataColumn FieldName="Discontinued" Width="50px" />
    </Columns>
</DxGrid>

@code {
    List<Product> Products { get; set; }
    IGrid MyGrid { get; set; }

    protected override void OnAfterRender(bool firstRender) {
         if(firstRender) {
             MyGrid.AutoFitColumnWidths();
         }
    }
}

Run Demo: Auto Fit Widths

To specify the column width in an exported document, use the ExportWidth property. For a code sample, see the following section: Specify Export Column Width.

Column Resize

Use the ColumnResizeMode property to allow users to resize grid columns. If allowed, the following resize operations are available to users:

  • Drag a column header’s right border.
  • Double-click a column’s right border to apply the optimal width based on column content.

You can set the ColumnResizeMode property to one of the following values:

Disabled
A user cannot resize columns.
NextColumn
When a user resizes a column, the width of the column to the right changes (considering the MinWidth value), but the Grid’s total width does not change. Users cannot change the width of the rightmost column.
ColumnsContainer
When a user resizes a column, all other columns retain their widths, but the width of the container that stores all Grid columns changes.

Run Demo: Column Resize

Text Customization

When a value does not fit into a cell as a single line, the cell displays multiple lines of text. Set the TextWrapEnabled property to false to disable word wrap (trim extra words). Instead of trimmed characters, the DxGrid component displays an ellipsis. Users can hover over the cell to display complete cell text in a tooltip.

Word Wrap Disabled

Run Demo: Virtual Scrolling

Use one of the following properties to align text in data cells or column captions:

Header Caption Alignment

Fixed (Anchored) Columns

If the combined column width exceeds the size of the component, DxGrid displays a horizontal scrollbar. If you want a column to always stay within the view, regardless of horizontal scrolling, anchor that column to the component’s left or right edge.

Users can reorder and resize fixed columns. They can control their visibility in the column chooser. However, users cannot move regular columns to a fixed column zone and vice versa.

Set a column’s FixedPosition property to Left or Right to freeze the column.

The following code snippet anchors (fixes) Ship Name and Shipped Date columns to the grid’s left and right edges:

<DxGrid Data="Data" >
    <Columns>
        <DxGridDataColumn FieldName="ShipName" FixedPosition="GridColumnFixedPosition.Left" Width="250px" />
        <DxGridDataColumn FieldName="ShipAddress" Width="350px" />
        <DxGridDataColumn FieldName="ShipCity" Width="200px" />
        <DxGridDataColumn FieldName="ShipPostalCode" Width="150px" />
        <DxGridDataColumn FieldName="ShipCountry" Width="200px" />
        <DxGridDataColumn FieldName="Freight" Width="100px" />
        <DxGridDataColumn FieldName="OrderDate" DisplayFormat="d" Width="120px" />
        <DxGridDataColumn FieldName="ShippedDate" FixedPosition="GridColumnFixedPosition.Right" Width="120px" />
    </Columns>
</DxGrid>

Fixed Columns

Run Demo: Fixed (Anchored) Columns

Export Settings

The grid exports data of every data column unless its ExportEnabled property is set to false. A column whose Visible property is set to false is exported as a hidden column (one that has a zero width).

You can use the Column.IsHidden property in the CustomizeColumn action to show and hide columns in the resulting document.

await Grid.ExportToXlsxAsync("ExportResult", new GridXlExportOptions() {
    CustomizeColumn = CustomizeColumn,
});
void CustomizeColumn(GridExportCustomizeColumnEventArgs e) {
    e.Column.IsHidden = false;
}

Save and Restore Column Settings

The Grid allows you to save its layout between application work sessions. Saved information includes the following column settings:

  • Group index
  • Sort index
  • Sort direction
  • Position
  • Visibility
  • Width

Refer to the following topic for additional information: GridPersistentLayout.

Column Chooser

The column chooser is a pop-up window that lists all grid columns (data, command, and selection) unless a column’s or its parent band’s ShowInColumnChooser property is set to false.

<DxGrid Data="Products">
    <Columns>
        <DxGridDataColumn FieldName="SupplierId" GroupIndex="0" Caption="Supplier" />
        <DxGridDataColumn FieldName="UnitPrice" AllowReorder="false" />
        <DxGridDataColumn FieldName="UnitsInStock" AllowReorder="false" />
        <DxGridDataColumn FieldName="QuantityPerUnit" ShowInColumnChooser="false" />
        <DxGridBandColumn Caption="Product">
            <Columns>
                <DxGridDataColumn FieldName="ProductName" Caption="Name" />
                <DxGridDataColumn FieldName="CategoryId" Visible="false" Caption="Category" />
            </Columns>
        </DxGridBandColumn>
        <DxGridDataColumn FieldName="Discontinued" FixedPosition="GridColumnFixedPosition.Right" />
    </Columns>
</DxGrid>

Column Chooser

Run Demo: Grid - Column Chooser Run Demo: Responsive Grid

The column chooser allows users to perform the following actions:

Show or hide columns
A user can select or clear a checkbox in the chooser to show or hide the corresponding column. This action changes the column’s Visible property value.
Reorder columns
A user can move a column to a new position within the column chooser. Such an operation changes the column’s VisibleIndex property value. Note that the chooser draws a thick line between regular and fixed columns. Columns cannot cross that line. Non-reorderable columns have a lock icon.

Grouped columns are hidden from the grid data area and disabled in the column chooser. You can set the ShowGroupedColumns property to true to display grouped columns in the grid layout and enable them in the chooser.

Call any of the ShowColumnChooser method overloads to display the column chooser.

<DxButton Text="Column Chooser" Click="ColumnChooserButton_Click" />
<DxGrid @ref="Grid" Data="Data">
    <Columns> ... </Columns>
</DxGrid>

@code {
    IGrid Grid { get; set; }

    void ColumnChooserButton_Click() {
        Grid.ShowColumnChooser();
    }
}

Column Chooser

To customize the appearance of column chooser items, handle the CustomizeElement event. The following code snippet highlights fixed columns in the column chooser.

<style>
    .highlighted-item {
        background-color: lightyellow !important;
    }
</style>

<DxGrid @ref="@Grid" Data="@Data" CustomizeElement="CustomizeColumnChooserItems" ... >
    <Columns>
        <DxGridSelectionColumn FixedPosition="GridColumnFixedPosition.Left" />
        <DxGridCommandColumn FixedPosition="GridColumnFixedPosition.Right" />
        <DxGridDataColumn FieldName="CompanyName" />
        <DxGridDataColumn FieldName="ContactName" />
        <DxGridDataColumn FieldName="Phone" Visible="false" />
    </Columns>
</DxGrid>

@code {
    //...
    void CustomizeColumnChooserItems(GridCustomizeElementEventArgs e) {
        if(e.ElementType == GridElementType.ColumnChooserItem && e.Column.FixedPosition != GridColumnFixedPosition.None) {
                e.CssClass = "highlighted-item";
        }              
    }
}

Custom Column Chooser Items

Task-Based Examples

This section contains code samples that demonstrate column functionality.

Create Columns at Runtime

The following code snippet demonstrates how you can create grid columns at runtime. Note that you can combine columns declared in markup and created at runtime.

@using System.Reflection
@using System.ComponentModel 
@inject EmployeeService EmployeeData

<DxGrid Data="employees">
    <Columns>
        <DxGridCommandColumn />
        @BuildGridColumns(typeof(Employee))
    </Columns>
</DxGrid>

@code {
    IEnumerable<Employee> employees;
    protected override async Task OnInitializedAsync() {
        employees = await EmployeeData.GetData();
    }
    RenderFragment BuildGridColumns(Type itemType) {
    var props = TypeDescriptor.GetProperties(itemType);
    return b => {
      foreach(PropertyDescriptor prop in props) {
        b.OpenComponent(0, typeof(DxGridDataColumn));
        b.AddAttribute(1, "FieldName", prop.Name);
        b.CloseComponent();
      }
    };
  }
}

Checkbox Setting

Display Text Instead of Checkboxes in a Column with Boolean Values

The grid shows checkboxes instead of column cell values if a column is bound to the Boolean or Nullable Boolean type.

Set the ShowCheckBoxInDisplayMode property to false to show text strings instead of checkboxes in display mode. To customize these strings, specify the following properties:

<DxGrid Data="products" PageSize="5">
    <Columns>
        <DxGridDataColumn FieldName="ProductName" />
        <DxGridDataColumn FieldName="UnitPrice" />
        <DxGridDataColumn FieldName="UnitsInOrder" />
        <DxGridDataColumn FieldName="Discontinued">
            <EditSettings>
                <DxCheckBoxSettings ShowCheckBoxInDisplayMode="false"
                                    CheckedDisplayText="Yes"
                                    IndeterminateDisplayText="Unknown"
                                    UncheckedDisplayText="No" />
            </EditSettings>
        </DxGridDataColumn>
    </Columns>
</DxGrid>

@code {
    private Product[]? products;
    protected override async Task OnInitializedAsync() {
        products = await ProductData.GetData();
    }
}

Check Box Setting

Sort Columns in Alphabetical Order in Column Chooser

The grid displays columns in the column chooser in the same order as they appear in the grid. This allows users to reorder grid columns with the column chooser.

If the column chooser in your application does not require the columns reorder feature, you can implement a custom column chooser to display columns alphabetically.

In the following code snippet, the DxListBox<TData, TValue> component lists grid columns. When a user selects or deselects List Box items, the SelectedItemsChanged event fires. The event handler changes the Visible property value according to current item selection.

<DxListBox Data="AllColumns" CssClass="list-box"
    SelectionMode="ListBoxSelectionMode.Multiple"
    ShowCheckboxes="true"
    TextFieldName="Caption"
    @bind-Values="VisibleColumns"
    SelectedItemsChanged="@((IEnumerable<IGridColumn> values) => SelectedItemsChanged(values))" />

<DxGrid @ref="Grid" Data="Data" PageSize="6" CssClass="my-class" >
    <Columns>
        <DxGridSelectionColumn Caption="Selection Column" />
        <DxGridCommandColumn Caption="Command Column" />
        <DxGridDataColumn FieldName="ContactName" Caption="Contact Name" />
        <DxGridDataColumn FieldName="CompanyName" Caption="Company Name" />
        <DxGridDataColumn FieldName="Country" Caption="Country" Visible="false" />
        <DxGridDataColumn FieldName="City" Caption="City" />
        <DxGridDataColumn FieldName="Phone" Caption="Phone" />
    </Columns>
</DxGrid>

@code {
    IGrid Grid { get; set; }
    object Data { get; set; }
    public IEnumerable<IGridColumn> AllColumns { get; set; }
    public IEnumerable<IGridColumn> VisibleColumns { get; set; }

    protected override async Task OnInitializedAsync() {
        Data = await NwindDataService.GetSuppliersAsync();
    }

    void SelectedItemsChanged(IEnumerable<IGridColumn> values) {
        Grid.BeginUpdate();
        foreach (var column in Grid.GetColumns())
            column.Visible = values.Contains(column);
        Grid.EndUpdate();
        VisibleColumns = values;
    }

    protected override void OnAfterRender(bool firstRender) {
        if(firstRender) {
            AllColumns = Grid.GetColumns().OrderBy(i => i, ColumnsComparerImpl.Default).ToList();
            VisibleColumns = Grid.GetVisibleColumns();
            StateHasChanged();
        }
    } 

    class ColumnsComparerImpl : IComparer<IGridColumn> {
        public static IComparer<IGridColumn> Default { get; } = new ColumnsComparerImpl(); 
        ColumnsComparerImpl() { } 
        int IComparer<IGridColumn>.Compare(IGridColumn x, IGridColumn y) {
            if(x is IGridSelectionColumn)
                return -1; 
            if(x is IGridCommandColumn && y is IGridDataColumn)
                return -1; 
            if(x is IGridDataColumn xData && y is IGridDataColumn yData) {
                var xName = !string.IsNullOrEmpty(xData.Caption) ? xData.Caption : xData.FieldName;
                var yName = !string.IsNullOrEmpty(yData.Caption) ? yData.Caption : yData.FieldName;
                return string.Compare(xName, yName);
            } 
        return 0;
        }
    } 
}

Grid - Unbound Full Name Column

Display Image Column

To display an image from a binary source, place an <img> element into CellDisplayTemplate and specify the src property. Review the example below:

<DxGridDataColumn FieldName="ImageData">
    <CellDisplayTemplate>
        <img style="width: 300px;" src="@GetImageSource(context)" />
    </CellDisplayTemplate>
</DxGridDataColumn>
const string ImageSourceFormat = "data:image/gif;base64,{0}";

void GetImageSource(GridCellDisplayTemplateContext context) {
    return string.Format(ImageSourceFormat, Convert.ToBase64String((byte[])context.Value));
}

Display Values of Two Fields in One Column

Implement an unbound column to display custom data in the grid.

In the following code snippet, the grid data source contains FirstName and LastName fields. To display full names in a column, create an unbound column and set its UnboundType property to String. You can calculate column values in two ways:

  • Create FirstName and LastName hidden columns and concatenate their values in the UnboundExpression property.

    <DxGrid Data="employees" >
        <Columns>
            <DxGridDataColumn FieldName="FirstName" Visible="false" />
            <DxGridDataColumn FieldName="LastName" Visible="false" />
            <DxGridDataColumn FieldName="FullName" UnboundType="GridUnboundColumnType.String" 
                              UnboundExpression="[FirstName]+ ' ' +[LastName]" />
            <DxGridDataColumn FieldName="HireDate" />
            <DxGridDataColumn FieldName="Email" />
        </Columns>
    </DxGrid>
    
    @code {
        Employee[]? employees;
        protected override async Task OnInitializedAsync() {
            employees = await EmployeeData.GetData();
        }
    }
    
  • Handle the UnboundColumnData event and use the GetRowValue(String) method to access values of the FirstName and LastName data fields.

    <DxGrid Data="employees" UnboundColumnData="Grid_UnboundColumnData">
        <Columns>
            <DxGridDataColumn FieldName="FullName" UnboundType="GridUnboundColumnType.String" />
            <DxGridDataColumn FieldName="HireDate" />
            <DxGridDataColumn FieldName="Email" />
        </Columns>
    </DxGrid>
    
    @code {
        Employee[]? employees;
        protected override async Task OnInitializedAsync() {
            employees = await EmployeeData.GetData();
        }
        void Grid_UnboundColumnData(GridUnboundColumnDataEventArgs e) {
            if(e.FieldName == "FullName") {
                e.Value = $"{e.GetRowValue("FirstName")} {e.GetRowValue("LastName")}";
            }
        }
    }
    

Grid - Unbound Full Name Column

Implement Data Editing without Command Column

To implement external command buttons, create buttons outside the grid, handle their click events and call the following methods:

StartEditNewRowAsync
Starts editing a new row.
StartEditRowAsync | StartEditDataItemAsync
Start editing the specified row or data item.
SaveChangesAsync
Initializes the save process and fires the EditModelSaving event. Handle this event to post changes to the underlying data source.
CancelEditAsync
Cancels row editing and discards changes.
ShowRowDeleteConfirmation | ShowDataItemDeleteConfirmation
Initializes the delete process and displays the delete confirmation dialog for the specified row or data item. When a user confirms the delete operation, the DataItemDeleting event fires. Handle this event to delete the record from the underlying data source.
.grid-container {
    width: 950px;
}
.pager-container {
    display: flex;
    justify-content: space-between;
    padding: 8px;
    border: 1px solid #d2d2d2;
    border-bottom: none;
}
<div class="grid-container">
    <div class="pager-container">
        <div>
            <DxButton Text="Add" Click="() => Grid.StartEditNewRowAsync()" />
            <DxButton Text="Edit" Click="() => Grid.StartEditRowAsync(Grid.GetFocusedRowIndex())" />
            <DxButton Text="Delete" Click="() => Grid.ShowRowDeleteConfirmation(Grid.GetFocusedRowIndex())" />  
        </div>
        <div>
            <DxButton Text="Save" Click="() => Grid.SaveChangesAsync()" Enabled="IsEditing" />
            <DxButton Text="Cancel" Click="() => Grid.CancelEditAsync()" Enabled="IsEditing"/>
        </div>
    </div>
    <DxGrid @ref="Grid" Data="DataSource" FocusedRowEnabled="true" EditMode="GridEditMode.EditRow"
            KeyFieldName="EmployeeId"
            CustomizeEditModel="Grid_CustomizeEditModel"
            EditModelSaving="Grid_EditModelSaving"
            DataItemDeleting="Grid_DataItemDeleting">
        <Columns>
            <DxGridDataColumn FieldName="FirstName" />
            <DxGridDataColumn FieldName="LastName" />
            <DxGridDataColumn FieldName="Title" />
        </Columns>
    </DxGrid>
</div>

@code {
    bool IsEditing => Grid != null ? Grid.IsEditing() : false;
    IEnumerable<EditableEmployee> DataSource { get; set; }
    IGrid Grid { get; set; }

    protected override async Task OnInitializedAsync() {
        DataSource = await NwindDataService.GetEmployeesEditableAsync();
    }
    void Grid_CustomizeEditModel(GridCustomizeEditModelEventArgs e) {
        if(e.IsNew) {
            var newEmployee = (EditableEmployee)e.EditModel;
            newEmployee.FirstName = "John";
            newEmployee.LastName = "Doe";
        }
    }
    async Task Grid_EditModelSaving(GridEditModelSavingEventArgs e) {
        if(e.IsNew)
            await NwindDataService.InsertEmployeeAsync((EditableEmployee)e.EditModel);
        else
            await NwindDataService.UpdateEmployeeAsync((EditableEmployee)e.DataItem, (EditableEmployee)e.EditModel);
        await UpdateDataAsync();
    }
    async Task Grid_DataItemDeleting(GridDataItemDeletingEventArgs e) {
        await NwindDataService.RemoveEmployeeAsync((EditableEmployee)e.DataItem);
        await UpdateDataAsync();
    }
    async Task UpdateDataAsync() {
        DataSource = await NwindDataService.GetEmployeesEditableAsync();
    }
}

Grid - Unbound Full Name Column