Columns Are Objects, Not Strings
A column is a GridColumn<TItem> with typed properties: Key binds it to a row field, Type picks the renderer and editor from thirteen values, and Sort, Filter, Editable, Pinned and Resizable are real booleans and enums. Leave Type off and the grid infers it from the data, as it does for the columns here.
Sort, Filter and Search
Turn them on per column with Sort and Filter, then drive them from C# when you need to: SortAsync takes GridSortExpression values with a SortingDirection enum, FilterAsync takes GridFilterExpression values, and SetQuickFilterAsync wires a search box across every column. Multi-column and tri-state sorting are one configuration object away.
Inline Editing with Undo and Redo
Editing opens the editor that matches the column type, and committed edits land on an undo stack. EditMode chooses whether a cell commits on its own or the whole row commits as a batch, EditTrigger chooses click or double click, and OnHistoryChanged tells your own toolbar when undo and redo became available.
Virtualized Rows
Only the rows in the viewport are in the DOM, so the row count stops being the thing that decides whether the page is usable. This is also why the grid needs a bounded Height: virtualization has to know what the viewport is before it can window anything.
One Package, No Toolchain
The grid engine and its dependencies are bundled as a self-contained ES module inside the NuGet package, served from _content/Blazor-ApexGrid/. No npm, CDN or script tag.
Typed From Top to Bottom
ApexGrid<TItem> with GridColumn<TItem> columns and typed configuration classes, so a wrong option name or value is a build error.
Thirteen Column Types
Number, String, Boolean, Select, Rating, Date, Image, Currency, Avatar, Badge, Progress, Sparkline and Status, each with a matching renderer and editor.
Editing with History
Cell or row editing, click or double click, and an undo stack that defaults to 100 committed edits.
Tree Data and Expansion
Nested rows derived from a path field on a flat collection, plus row expansion with an HTML detail template.
State Persistence
GetStateAsync and SetStateAsync move a whole view, sort and filters and pins and widths, in and out as JSON.
29 Typed Events
Every grid event is an EventCallback with a typed payload that hands back your own TItem rather than a dictionary.
Server and WebAssembly
Async IJSRuntime interop imported after first render, so neither hosting model is a special case. Multi-targets .NET 8, 9 and 10.
Blazor Data Grid FAQ
What is Blazor-ApexGrid?
Blazor-ApexGrid is a Blazor wrapper for the ApexGrid data grid that exposes it as a typed ApexGrid<TItem> Razor component. Columns are C# objects, configuration is C# classes and enums, and all 29 grid events arrive as strongly typed EventCallbacks. The grid engine is bundled inside the NuGet package as a self-contained ES module, so there is no script tag, CDN reference or npm step.
How do I install the Blazor data grid?
Run dotnet add package Blazor-ApexGrid, then add @using Blazor_ApexGrid.Components and @using Blazor_ApexGrid.Models to your _Imports.razor. There is no service to register and no asset to copy: the JavaScript and styles are served automatically from _content/Blazor-ApexGrid/.
Which .NET versions does Blazor-ApexGrid support?
Version 1.0.0 multi-targets .NET 8, .NET 9 and .NET 10, so a .NET 8 LTS project can adopt it without moving framework.
Does the Blazor data grid work in Blazor Server?
Yes. Every interop call goes through IJSRuntime and IJSObjectReference, and the module is imported in OnAfterRenderAsync rather than during prerendering, so Blazor Server, Blazor WebAssembly and InteractiveAuto all work without a special case.
Why does my Blazor grid render blank?
Usually one of two things. First, the render mode: from .NET 8 a Blazor Web App renders statically by default, so a component that needs JavaScript interop must opt into InteractiveServer, InteractiveWebAssembly or InteractiveAuto. Second, height: the grid virtualizes rows, which needs a bounded height, so the Height parameter must resolve to a real value rather than collapsing to zero.
How do column keys map to my C# model?
A column Key is the row property under its serialized name, which is camelCase. A Name property is referenced as "name" and a GrossValue property as "grossValue". The same applies to the tree PathKey and to the {field} tokens in a detail template.
Do I need a license key for the Blazor data grid?
The package exposes no license key property, and the grid runs with no key. ApexGrid is dual licensed: the Community License is free for individuals, non-profits, educators and organizations under 2 million USD in annual revenue, and a Commercial License applies above that threshold. Embedding it in a product used by other people needs the OEM License at any revenue.
Does the Blazor package include row grouping, pivoting or spreadsheet formulas?
No. Blazor-ApexGrid 1.0.0 bundles the community ApexGrid core, so the enterprise analytics tier is not reachable from the C# surface. That tier covers row grouping, column aggregations, pivoting, the server-side row model, the Excel-style set filter, the advanced filter builder, the columns tool panel, range selection, integrated charts, cell formulas, the AI toolkit, the context menu and XLSX export.
Can I save and restore the grid state?
Yes. GetStateAsync returns a JSON-safe snapshot of sort, filters, paging, column order, pins and widths, which you can persist anywhere, and SetStateAsync restores it. Only the slices present in a snapshot are applied, so a partial snapshot is valid. GetSchemaAsync returns a machine-readable description of the grid, which is useful for driving a view editor or an AI layer.
Ready to build a grid in C#?
One dotnet add package, two using directives, and an interactive render mode. The running sample carries every feature on this page.
See the live sample