DataGrid

A full-featured data grid for Blazor with sorting, filtering, paging, virtual scrolling, grouping, inline editing, row selection, column templates, column reorder, stacked headers, infinite scroll, cell tooltips, copy with headers, conditional formatting, ObservableCollection binding, and CSV/Excel/PDF export. Works in Server, WebAssembly, and Auto render modes.

Installation

dotnet add package Arcadia.DataGrid

Add the stylesheet to your App.razor or _Host.cshtml:

<link href="_content/Arcadia.DataGrid/css/arcadia-datagrid.css" rel="stylesheet" />

No service registration is required. The component is ready to use after adding the package and stylesheet.

Basic Usage

<ArcadiaDataGrid TItem="Employee" Data="@employees">
    <ArcadiaColumn TItem="Employee" Title="Name" Field="@(e => e.Name)" />
    <ArcadiaColumn TItem="Employee" Title="Department" Field="@(e => e.Department)" />
    <ArcadiaColumn TItem="Employee" Title="Salary" Field="@(e => e.Salary)" Format="C0" Align="right" />
</ArcadiaDataGrid>

@code {
    private List<Employee> employees = new()
    {
        new("Alice", "Engineering", 95000),
        new("Bob", "Marketing", 72000),
        new("Carol", "Engineering", 105000),
    };

    record Employee(string Name, string Department, decimal Salary);
}

ArcadiaDataGrid Parameters

ParameterTypeDefaultDescription
DataIReadOnlyList<TItem>?nullIn-memory collection of row items. When null, the grid shows EmptyMessage
PageSizeint25Rows per page. 0 = show all (no paging)
PageSizeOptionsint[][10, 25, 50, 100]Page size options for the dropdown
SortablebooltrueEnable click-to-sort on column headers. Individual columns can override
StripedbooltrueAlternating background shading on even/odd rows
HoverablebooltrueBackground highlight on the row under the cursor
DenseboolfalseReduce row height and cell padding for a denser layout
FixedHeaderbooltrueKeep column headers fixed at the top during vertical scroll. Requires Height
Heightstring?nullFixed height with scroll (e.g., "400px"). Null = auto height
LoadingboolfalseRender animated skeleton rows while awaiting an async fetch
EmptyMessagestring"No data available"Text shown when Data is null or empty and Loading is false
ShowRowSelectorboolfalseShow row selector column with row numbers and state indicators
ShowRowNumbersbooltrueDisplay row numbers in the row selector column. Requires ShowRowSelector
FilterableboolfalseAdd a filter input row below headers
SelectableboolfalseAllow rows to be selected by clicking
MultiSelectboolfalseAdd a checkbox column for multi-select. Requires Selectable
SelectedItemsHashSet<TItem>?nullCurrently selected items. Two-way bindable
SelectedItemsChangedEventCallback<HashSet<TItem>>Callback when the selection set changes
LoadDataEventCallback<DataGridLoadArgs>Server-side data loading callback. When set, the grid operates in server-side mode
ServerTotalCountint?nullTotal matching rows on the server for page count calculation. Required with LoadData
DetailTemplateRenderFragment<TItem>?nullDetail row template. When set, rows become expandable
ChildContentRenderFragment?nullChild content slot for ArcadiaColumn components
SortChangedEventCallback<SortDescriptor?>Callback when column sorting changes
OnRowEditEventCallback<TItem>Callback when an inline edit is committed (Enter or blur)
GroupBystring?nullColumn key whose values group rows into collapsible sections
VirtualizeRowsboolfalseEnable virtual scrolling for large datasets. Requires Height. Disables pagination
ItemSizefloat40Estimated row height in pixels for the virtualizer
OverscanCountint5Extra rows rendered outside the viewport to reduce flicker
Propertystring?nullProperty name to use as the unique row identifier for tracking and state persistence
SelectionModeSelectionModeNoneRow selection mode: None, Single, Multiple. Replaces Selectable/MultiSelect with a single enum
BatchEditboolfalseEnable batch editing mode. Edits are staged in memory until explicitly committed
OnBatchCommitEventCallback<IReadOnlyList<TItem>>Callback when staged batch edits are committed. Receives all modified items
StateKeystring?nullUnique key for persisting grid state (sort, filter, page, column order) to browser storage
OnStateChangedEventCallback<DataGridState>Callback when grid state changes. Fires on sort, filter, page, or column reorder
QuickFilterstring?nullCross-column search text. Rows where any column value contains this text are shown. Two-way bindable
QuickFilterChangedEventCallback<string?>Callback when the quick filter text changes
ShowToolbarboolfalseShow the toolbar above the grid with export button, quick filter search, and filter toggle
ContextMenuTemplateRenderFragment<TItem>?nullTemplate for a custom right-click context menu on rows
OnContextMenuEventCallback<DataGridContextMenuArgs<TItem>>Callback when a row is right-clicked. Use to show a custom context menu
EmptyTemplateRenderFragment?nullCustom template shown when Data is null or empty. Overrides EmptyMessage text
SyncGroupstring?nullSync group name for linked chart components. Charts sharing the same SyncGroup synchronize tooltip, crosshair, and zoom state
Classstring?nullAdditional CSS classes on the root element
Stylestring?nullInline style on the root element

ArcadiaColumn Parameters

ParameterTypeDefaultDescription
FieldFunc<TItem, object>?nullValue accessor lambda for this column
Titlestring""Column header text
Sortablebool?nullWhether this column is sortable. Null inherits from grid-level Sortable
Widthstring?nullCSS width (e.g., "200px", "30%"). Null = auto
Alignstring"left"Text alignment: left, center, right
Formatstring?null.NET format string for cell values (e.g., "C2", "d", "N0")
TemplateRenderFragment<TItem>?nullCustom cell content template
HeaderTemplateRenderFragment?nullCustom header content template
Filterablebool?nullWhether this column is filterable. Null inherits from grid
VisiblebooltrueWhether this column is visible
FrozenboolfalsePin this column to the left edge. Requires Width to be set
EditableboolfalseWhether this column supports inline editing
EditTemplateRenderFragment<TItem>?nullCustom edit template for inline editing
AggregateAggregateTypeNoneFooter aggregate: None, Sum, Average, Count, Min, Max
FooterTemplateRenderFragment?nullCustom footer template (overrides Aggregate when set)
CellClassFunc<TItem, string?>?nullDynamic CSS class for cells in this column

Live Data (ObservableCollection)

The DataGrid automatically detects when Data is an ObservableCollection<T> and re-renders when items are added, removed, or cleared. No manual StateHasChanged() needed.

Basic Usage

@using System.Collections.ObjectModel

<ArcadiaDataGrid TItem="Order" Data="@_orders">
    <ArcadiaColumn TItem="Order" Field="@(d => (object)d.Id)" Title="ID" />
    <ArcadiaColumn TItem="Order" Field="@(d => (object)d.Product)" Title="Product" />
</ArcadiaDataGrid>

@code {
    private ObservableCollection<Order> _orders = new(initialData);

    // Adding an item auto-updates the grid — no StateHasChanged needed
    private void AddOrder() => _orders.Add(new Order(...));
}

SignalR Integration

// In a Blazor Server component
hubConnection.On<Order>("NewOrder", order =>
{
    _orders.Insert(0, order);
    // Grid updates automatically!
});

Batch Edit Guard

During batch editing, live updates are suppressed to avoid disrupting the user’s in-progress edits. Updates resume automatically when the batch is committed or discarded.

Debouncing

Rapid changes (e.g., 100 items added in 50ms) are automatically debounced into a single re-render for optimal performance.

Feature Pages

  • Sorting — Click-to-sort, multi-direction cycling, SortChanged event
  • Filtering — Per-column filter row, FilterDescriptor, operators
  • Selection — Single and multi-select, checkbox column, SelectedItems binding
  • Editing — Inline editing, EditTemplate, OnRowEdit event
  • Grouping — GroupBy column key, collapsible groups
  • Templates — Cell, header, footer, detail templates and aggregates
  • Virtual Scrolling — Render 10K+ rows at 60fps
  • Themes — 6 built-in themes, 3 density modes, CSS custom properties
  • Export — CSV export respecting current sort and filters