
Syncfusion Blazor Datagrid
- 271 installs
- 4 repo stars
- Updated July 28, 2026
- syncfusion/blazor-ui-components-skills
Use syncfusion-blazor-datagrid for development tasks
About
syncfusion-blazor-datagrid: A skill for development. This provides functionality for development workflows.
- syncfusion-blazor-datagrid
Syncfusion Blazor Datagrid by the numbers
- 271 all-time installs (skills.sh)
- +14 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #1,436 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/syncfusion/blazor-ui-components-skills --skill syncfusion-blazor-datagridAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 271 |
|---|---|
| repo stars | ★ 4 |
| Last updated | July 28, 2026 |
| Repository | syncfusion/blazor-ui-components-skills ↗ |
What it does
Use syncfusion-blazor-datagrid for development tasks
Files
***
Implementing Syncfusion Blazor DataGrid
The Syncfusion Blazor DataGrid (SfGrid<TValue>) is a high-performance, feature-rich component for displaying and manipulating tabular data. It supports data binding, sorting, filtering, grouping, paging, editing, selection, aggregates, export, virtual/infinite scrolling, templates, and more.
NuGet: Syncfusion.Blazor.Grid + Syncfusion.Blazor.Themes Namespace: Syncfusion.Blazor.Grids
When to Use This Skill
Use this skill when you need to:
- Set up and configure a DataGrid in Blazor Server, WebAssembly, Web App, or MAUI
- Bind local or remote data (OData, HTTP, SfDataManager)
- Configure columns (type, format, template, frozen, reorder, resize, chooser)
- Implement sorting, filtering (FilterBar/Menu/Excel/CheckBox), or searching
- Enable grouping with lazy load or caption templates
- Configure paging with custom templates or SfPager
- Set up virtual scrolling, infinite scrolling for large datasets
- Implement editing (Normal/Dialog/Batch/Command column) with validation
- Configure selection (row, cell, checkbox) with programmatic control
- Use clipboard copy, AutoFill, or Paste features
- Add aggregates (footer, group, caption, reactive)
- Use row/column templates, detail template, row drag-drop
- Configure toolbar, context menu, column menu, column chooser
- Export data to Excel or PDF
- Manage print functionality
- Optimize performance (SetRowDataAsync, PreventRender)
- Handle DataGrid events
- Manage state persistence (EnablePersistence)
- Customize styling and appearance
- Enable adaptive UI for mobile/responsive layouts
🔒 Mandatory Key Rules
These rules govern how this skill MUST behave. They are mandatory and must be strictly followed.
1. Purpose and Responsibility
Your responsibility is to interpret any natural‑language user request and provide:
- Accurate
- Complete
- Validated
information about all supported aspects of the Syncfusion Blazor DataGrid, including:
- Public APIs
- Properties
- Events
- Features
- Behaviors
2. Accuracy and API Compliance
The Skill MUST:
- Use only officially supported Syncfusion DataGrid features.
- NEVER invent APIs, methods, properties, events, behaviors, or future features.
- NEVER provide unsupported or hypothetical code samples.
- ALWAYS follow official Syncfusion component design patterns.
If a feature is not supported:
- Clearly state the limitation.
- Suggest a supported alternative when possible.
3. Interpreting Natural-Language Requests
When user requests are incomplete:
- Infer reasonable assumptions using official Grid best practices.
- Fill missing gaps with accurate and relevant information.
- Request clarification only when essential.
4. Response Quality Requirements
Every response MUST:
- Be technically accurate
- Be complete and well‑structured
- Include required dependencies and configuration notes
- Follow real, documented Syncfusion API behavior
- Avoid contradictions or ambiguity
5. Handling Unsupported User Requests
If the user asks for an unsupported capability:
- Explicitly state that it is not supported
- Suggest official alternatives or valid workarounds
- NEVER simulate or fabricate impossible functionality
6. Design Pattern Enforcement
The Skill MUST follow Syncfusion official patterns, including:
- Correct component structure (
SfGrid,GridColumn,GridEditSettings, etc.) - Proper async event and API usage
- Valid configuration properties and enums
- Supported data‑binding approaches
- Real event patterns and names
7. Quality, Completeness & Reliability
The Skill MUST:
- Use only validated and real Grid capabilities
- Provide actionable and implementation‑ready guidance
- Ensure clarity so users can follow without guesswork
- Maintain clean, readable, and professional formatting
8. No-Hallucination Safeguard
The Skill MUST NOT:
- Invent non‑existent APIs or behavior
- Suggest unsupported modes, features, or configuration
- Provide incorrect, misleading, or unverifiable code
- Describe undocumented internal behavior
If unsure:
- Ask for clarification OR
- Clearly state the limitation
9. Event Name Verification Requirement
CRITICAL: Event names MUST be verified against references/events.md BEFORE providing code examples. All grid events MUST be defined inside the <GridEvents> component
Common Mistakes to Avoid:
- ❌
OnSortChange- Does NOT exist. UseSorting,Sortedinstead - ❌
OnFilterChange- Does NOT exist. UseFiltering,Filteredinstead - ❌
OnPageChange- Does NOT exist. UsePageChanging,PageChangedinstead - ❌
OnGroupChange- Does NOT exist. UseGrouping,Groupedinstead
Rule: ALWAYS cross-reference references/events.md for:
- Exact event names (case-sensitive)
- Event argument types
- Whether events are cancelable
- When they fire (before/after operation)
Verification Checklist Before Providing Event Code:
1. Check if event name exists in references/events.md 2. Verify the correct EventArgs type 3. Confirm Cancelable status (✅ or ❌) 4. Test against actual Syncfusion documentation 5. Never assume naming conventions (e.g., On prefix, Change suffix)
---
Strict Rules for Grid Events
1. Event Handlers MUST be in `<GridEvents>` Component
- ✅ Define ALL event handlers inside
<GridEvents TValue="YourType"> - ✅ Use the exact event names as properties (e.g.,
DataBound,RowSelecting,Grouped) - ❌ DO NOT use
@onEventNamesyntax on<SfGrid> - ❌ DO NOT define event handlers on any root element
2. Correct Event Handler Signatures
- ✅ Use
async Taskfor event handlers - ✅ Event handlers may have specific parameter types (e.g.,
GridEventArgs,RowSelectEventArgs) - ✅ Some events have no parameters (e.g.,
DataBound(),Created()) - ❌ Do not use synchronous
voidmethods for async operations
3. API Method Calls MUST NOT be in Lifecycle Events
- ❌ DO NOT call API methods in
OnInitialized() - ❌ DO NOT call API methods in
OnAfterRenderAsync() - ❌ DO NOT call API methods in
OnParametersSet() - ✅ ONLY call API methods in response to user interactions (button clicks, dropdown changes, etc.)
- ✅ API methods CAN be called inside GridEvents handlers
4. Use Async/Await Pattern
- ✅ Always use
awaitwith async API methods - ✅ Define event handlers as
async Task - ✅ Mark code block methods as
async Task - ❌ Do not use synchronous method calls for async operations
5. Grid Reference Required for API Calls
- ✅ Use
@ref="Grid"to get the Grid instance - ✅ Use the reference to call API methods (e.g.,
await Grid.GroupColumnAsync()) - ❌ Do not attempt to call methods without a reference
6. Event Types Must Match GridEvents TValue
- ✅ Set
TValue="YourDataType"to match your data model - ✅ All event handlers will be properly typed with this model
- ❌ Do not use generic or wrong type for TValue
---
Navigation Guide
Setup & Getting Started
📄 Read: references/getting-started.md
- NuGet install,
_Imports.razor,Program.cs, theme/script setup, basic grid
📄 Read: references/getting-started-app-types.md
- Server App, Web App (Auto/WASM), MAUI variants
Data
📄 Read: references/data-binding.md
- Local (List, ExpandoObject, DynamicObject, DataTable, ObservableCollection)
Connecting to Adaptors (Remote Data)
📄 Read: references/odatav4-adaptor.md
- OData V4 service setup, ODataConventionModelBuilder, [EnableQuery], automatic $filter/$orderby/$skip/$top, CRUD with PATCH/DELETE
📄 Read: references/web-api-adaptor.md
- Web API with { Items, Count } response, manual $filter/$orderby/$skip/$top QueryString parsing, CRUD with GET/POST/PUT/DELETE
- Security note: Do NOT bind
SfDataManager.Urlto arbitrary user-supplied URLs. Use an operator-configured string variable (for exampleUrl="@DataApiUrl"whereDataApiUrlis read fromALLOWED_API_URLin configuration), an internal proxy/gateway, field/operator whitelists, and server-side validation/sanitization. See references/web-api-adaptor.mdSecurity Considerationsfor examples.
📄 Read: references/url-adaptor.md
- Custom API with { result, count } response, DataManagerRequest POST body, DataOperations helpers, InsertUrl/UpdateUrl/RemoveUrl/CrudUrl/BatchUrl
- Security note: Use a configuration-backed URL variable (for example
Url="@DataApiUrl"whereDataApiUrlis read fromALLOWED_API_URLin configuration), avoid user-supplied endpoints, and route third-party requests through an internal proxy/gateway. See references/url-adaptor.md for examples and configuration snippets.
📄 Read: references/custom-adaptor.md
- DataAdaptor abstract class, override Read/Insert/Update/Remove/BatchUpdate, service injection, adaptor as component, custom parameters via Query.AddParams
- Security note: When implementing
CustomAdaptor, do not trustdm.Paramsor user-supplied endpoints. Use operator-configured endpoints, validatedm.Params, whitelist fields/operators, and route third-party calls through a proxy. See references/custom-adaptor.mdSecurity Considerationsfor examples.
Columns
📄 Read: references/columns.md
- ColumnType, Format, TextAlign, frozen, reorder, resize, chooser, stacked headers, column menu, foreign key
📄 Read: references/cell.md
- QueryCellInfo, CustomAttributes, ClipMode, GridLines, tooltips
Sorting, Filtering, Searching
📄 Read: references/sorting.md
- AllowSorting, multi-sort, SortColumnAsync, ClearSortingAsync
📄 Read: references/filtering.md
- AllowFiltering, FilterType (FilterBar/Menu/Excel/CheckBox), operators, FilterByColumnAsync
📄 Read: references/searching.md
- Toolbar Search, SearchAsync, GridSearchSettings
Grouping & Paging
📄 Read: references/grouping.md
- AllowGrouping, lazy load grouping, CaptionTemplate, programmatic group/ungroup
📄 Read: references/paging.md
- AllowPaging, GridPageSettings, pager template, GoToPageAsync
Scrolling
📄 Read: references/scrolling.md
- Height/Width, sticky header, ScrollIntoViewAsync
📄 Read: references/virtual-scrolling.md
- EnableVirtualization, EnableColumnVirtualization, OverscanCount, limitations
📄 Read: references/infinite-scrolling.md
- EnableInfiniteScrolling, GridInfiniteScrollSettings, cache mode, limitations
Editing
📄 Read: references/editing.md
- GridEditSettings, EditMode (Normal/Dialog/Batch/CommandColumn), ValidationRules, EditType, EditTemplate, CRUD methods
Read: references/editing-patterns.md
- Cancel edit based on condition, disable editing for specific rows
- Provide new/edited item via events, default column values, new row position
- Always-show add-new-row form, delete multiple rows, single-click editing
- Save new row at a specific index, inline template editing
📄 Read: references/editing-validation.md
- Per-column
ValidationRules, Data Annotation attributes ([Required],[Range], etc.) - Custom validation attributes, complex type validation, custom validator component
Selection
📄 Read: references/selection.md
- AllowSelection, SelectionMode, SelectionType, checkbox selection, programmatic selection
📄 Read: references/clipboard.md
- Clipboard copy (Ctrl+C / Ctrl+Shift+H), CopyAsync, AutoFill drag handle, Paste (Ctrl+V), batch editing requirements
Aggregates
📄 Read: references/aggregates.md
- GridAggregates, AggregateType, FooterTemplate, GroupFooterTemplate, GroupCaptionTemplate, reactive aggregates
Row Features & Templates
📄 Read: references/row-features.md
- RowDataBound, row drag-drop, row height, row spanning, RowTemplate
📄Read: references/templates-structural.md
- ColumnTemplate (image, hyperlink, checkbox, SfChip), HeaderTemplate, RowTemplate, RowTemplate formatting, DetailTemplate, expand/collapse APIs, expand on load, hide expand icon, custom CSS icons, hierarchical nested Grid
📄 Read: references/templates-interactive.md
- ToolbarTemplate, Column EditTemplate, GridEditSettings Template, disable inputs on add vs edit, triple underscore nested binding, focus editor on dialog open, RowUpdating transform, FooterTemplate, CaptionTemplate, custom Blazor component in caption, locale customization, PagerTemplate
Toolbar, Context Menu
📄 Read: references/toolbar.md
- Built-in/custom toolbar items, OnToolbarClick, ToolbarTemplate
📄 Read: references/context-menu.md
- ContextMenuItems, custom items, ContextMenuItemClicked
Export & Print
📄 Read: references/excel-export.md
- AllowExcelExport, ExportToExcelAsync, ExcelExportProperties, theme/template export
📄 Read: references/pdf-export.md
- AllowPdfExport, ExportToPdfAsync, PdfExportProperties, template PDF export
📄 Read: references/print.md
- PrintAsync, PrintMode
Performance, Events, State
📄 Read: references/performance.md
- SetRowDataAsync, PreventRender, WebAssembly optimization, column virtualization tips
📄 Read: references/events.md
- Complete GridEvents<TValue> reference: all edit, selection, filter, sort, group, page, toolbar, export events
📄 Read: references/state-management.md
- EnablePersistence, GetPersistDataAsync, SetPersistDataAsync, ResetPersistDataAsync
Styling & Adaptive UI
📄 Read: references/style-and-appearance.md
- CSS classes for grid, header, rows, filtering, editing, grouping, aggregates
📄 Read: references/adaptive-layout.md
- EnableAdaptiveUI, RowRenderingMode, AdaptiveUIMode, mobile-responsive patterns
Quick Start
@page "/datagrid-demo"
@using Syncfusion.Blazor.Grids
<SfGrid DataSource="@Orders" AllowPaging="true" AllowSorting="true" AllowFiltering="true">
<GridPageSettings PageSize="10"></GridPageSettings>
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" IsPrimaryKey="true" Width="120" TextAlign="TextAlign.Right"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer" Width="150"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight" Format="C2" Width="120" TextAlign="TextAlign.Right"></GridColumn>
<GridColumn Field="OrderDate" HeaderText="Order Date" Format="d" Width="150" Type="ColumnType.Date"></GridColumn>
<GridColumn Field="ShipCountry" HeaderText="Ship Country" Width="150"></GridColumn>
</GridColumns>
</SfGrid>
@code {
public List<Order> Orders = new List<Order>
{
new Order { OrderID = 10248, CustomerID = "VINET", Freight = 32.38, OrderDate = new DateTime(1996,7,4), ShipCountry = "France" },
new Order { OrderID = 10249, CustomerID = "TOMSP", Freight = 11.61, OrderDate = new DateTime(1996,7,5), ShipCountry = "Germany" },
};
public class Order
{
public int OrderID { get; set; }
public string CustomerID { get; set; }
public double Freight { get; set; }
public DateTime OrderDate { get; set; }
public string ShipCountry { get; set; }
}
}Common Patterns
Grid with Editing + Toolbar
<SfGrid DataSource="@Orders" Toolbar="@(new List<string>() { "Add","Edit","Delete","Update","Cancel" })">
<GridEditSettings AllowAdding="true" AllowEditing="true" AllowDeleting="true" Mode="EditMode.Normal"></GridEditSettings>
<GridColumns>
<GridColumn Field="OrderID" IsPrimaryKey="true" ValidationRules="@(new ValidationRules{Required=true})"></GridColumn>
<GridColumn Field="CustomerID" ValidationRules="@(new ValidationRules{Required=true})"></GridColumn>
<GridColumn Field="Freight" EditType="EditType.NumericEdit"></GridColumn>
</GridColumns>
</SfGrid>Grid with Grouping + Paging
<SfGrid DataSource="@Orders" AllowGrouping="true" AllowPaging="true">
<GridGroupSettings Columns="@(new string[]{"ShipCountry"})"></GridGroupSettings>
<GridPageSettings PageSize="10"></GridPageSettings>
<GridColumns>
<GridColumn Field="OrderID" Width="120"></GridColumn>
<GridColumn Field="CustomerID" Width="150"></GridColumn>
<GridColumn Field="ShipCountry" Width="150"></GridColumn>
</GridColumns>
</SfGrid>Grid Reference for Programmatic Control
<SfGrid @ref="Grid" DataSource="@Orders">...</SfGrid>
@code {
SfGrid<Order> Grid;
// Programmatic operations:
// await Grid.SortColumnAsync("OrderID", SortDirection.Ascending, false);
// await Grid.FilterByColumnAsync("ShipCountry", "equal", "France");
// await Grid.GoToPageAsync(2);
// await Grid.StartEditAsync();
// await Grid.SelectRowAsync(0);
}Key Properties at a Glance
| Property | Description |
|---|---|
DataSource | Bind IEnumerable<T> or DataManagerRequest |
AllowPaging | Enable paging |
AllowSorting | Enable sorting |
AllowFiltering | Enable column filtering |
AllowGrouping | Enable row grouping |
AllowSelection | Enable row/cell selection |
Height / Width | Fixed dimensions for scrolling |
Toolbar | Built-in or custom toolbar items |
EnableVirtualization | Row virtualization for large data |
EnableInfiniteScrolling | Infinite scroll loading |
EnablePersistence | Save state to localStorage |
EnableAdaptiveUI | Mobile-responsive rendering |
````
Adaptive UI Layout
Table of Contents
- Overview
- Render Adaptive Dialogs
- Vertical Row Rendering
- Limit Adaptive Layout to Mobile Only
- Supported Features in Vertical Mode
- Key Properties
Overview
The Syncfusion Blazor DataGrid includes an adaptive UI designed for small screens. When EnableAdaptiveUI="true", the grid renders filter, sort, column chooser, column menu, and edit dialogs in a full-screen mobile-friendly layout. Rows can optionally render vertically for improved readability on narrow viewports.
When to use this reference:
- Building mobile-responsive Blazor apps with DataGrid
- Rendering filter/sort/edit dialogs in full-screen on small devices
- Switching row layout to vertical mode for narrow screens
- Limiting adaptive behavior to mobile screen sizes only
Render Adaptive Dialogs
Set EnableAdaptiveUI="true" to activate mobile-optimized full-screen dialogs for filter, sort, and edit operations:
@using Syncfusion.Blazor.Grids
<div class="content-wrapper e-bigger e-adaptive-demo">
<div class="e-mobile-layout">
<div class="e-mobile-content">
<SfGrid DataSource="@AdaptiveData"
AllowPaging="true"
AllowSorting="true"
AllowFiltering="true"
EnableAdaptiveUI="true"
Toolbar="@(new List<string>() { "Add", "Edit", "Delete", "Cancel", "Update", "Search" })"
Height="100%">
<GridFilterSettings Type="FilterType.Excel"></GridFilterSettings>
<GridEditSettings AllowAdding="true" AllowEditing="true" AllowDeleting="true"
Mode="EditMode.Dialog"></GridEditSettings>
<GridColumns>
<GridColumn Field="SNO" HeaderText="S NO" IsPrimaryKey="true" Width="150"
ValidationRules="@(new ValidationRules{ Required=true })"></GridColumn>
<GridColumn Field="Model" HeaderText="Model" Width="200"
ValidationRules="@(new ValidationRules{ Required=true })"></GridColumn>
<GridColumn Field="Developer" HeaderText="Developer" Width="200"></GridColumn>
<GridColumn Field="ReleaseDate" HeaderText="Released Date"
EditType="EditType.DatePickerEdit" Format="yyyyMMM" Width="200"></GridColumn>
<GridColumn Field="AndroidVersion" HeaderText="Android Version" Width="200"></GridColumn>
</GridColumns>
</SfGrid>
</div>
</div>
</div>
@code {
public List<AdaptiveDetails> AdaptiveData { get; set; }
protected override void OnInitialized()
{
AdaptiveData = AdaptiveDetails.GetAllModels();
}
}UseEditMode.DialogwithEnableAdaptiveUIso edit forms render as full-screen dialogs on mobile.
Vertical Row Rendering
Set RowRenderingMode="RowDirection.Vertical" to display each row's fields stacked vertically. This improves data readability on narrow screens.
EnableAdaptiveUI="true"must be set for vertical row rendering to work. The default isRowDirection.Horizontal.
@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor.DropDowns
<SfDropDownList TValue="RowDirection" TItem="DropDownOrder" DataSource="@DropDownValue" Width="120px">
<DropDownListFieldSettings Text="Text" Value="Value"></DropDownListFieldSettings>
<DropDownListEvents ValueChange="OnChange" TValue="RowDirection" TItem="DropDownOrder"></DropDownListEvents>
</SfDropDownList>
<SfGrid @ref="Grid"
DataSource="@AdaptiveData"
AllowPaging="true"
AllowSorting="true"
AllowFiltering="true"
EnableAdaptiveUI="true"
RowRenderingMode="@RowDirectionValue"
Toolbar="@(new List<string>() { "Add", "Edit", "Delete", "Cancel", "Update", "Search" })"
Height="100%">
<GridFilterSettings Type="FilterType.Excel"></GridFilterSettings>
<GridEditSettings AllowAdding="true" AllowEditing="true" AllowDeleting="true"
Mode="EditMode.Dialog"></GridEditSettings>
<GridColumns>
<GridColumn Field="SNO" HeaderText="S NO" IsPrimaryKey="true" Width="150"></GridColumn>
<GridColumn Field="Model" HeaderText="Model" Width="200"></GridColumn>
<GridColumn Field="Developer" HeaderText="Developer" Width="200"></GridColumn>
<GridColumn Field="ReleaseDate" HeaderText="Released Date"
EditType="EditType.DatePickerEdit" Format="yyyyMMM" Width="200"></GridColumn>
<GridColumn Field="AndroidVersion" HeaderText="Android Version" Width="200"></GridColumn>
</GridColumns>
</SfGrid>
@code {
private SfGrid<AdaptiveDetails> Grid;
public RowDirection RowDirectionValue { get; set; } = RowDirection.Horizontal;
public List<AdaptiveDetails> AdaptiveData { get; set; }
protected override void OnInitialized()
{
AdaptiveData = AdaptiveDetails.GetAllModels();
}
public class DropDownOrder
{
public string Text { get; set; }
public RowDirection Value { get; set; }
}
List<DropDownOrder> DropDownValue = new List<DropDownOrder>
{
new DropDownOrder() { Text = "Horizontal", Value = RowDirection.Horizontal },
new DropDownOrder() { Text = "Vertical", Value = RowDirection.Vertical },
};
public void OnChange(ChangeEventArgs<RowDirection, DropDownOrder> args)
{
RowDirectionValue = args.Value;
}
}Limit Adaptive Layout to Mobile Only
By default, EnableAdaptiveUI="true" applies the adaptive layout on both mobile and desktop. To restrict it to mobile screen sizes only, set AdaptiveUIMode="AdaptiveMode.Mobile":
<SfGrid @ref="Grid"
ID="Grid"
DataSource="@Orders"
EnableAdaptiveUI="true"
RowRenderingMode="RowDirection.Horizontal"
AdaptiveUIMode="AdaptiveMode.Mobile"
AllowPaging="true"
AllowSorting="true"
AllowGrouping="true"
AllowSelection="true"
AllowFiltering="true"
AllowExcelExport="true"
AllowPdfExport="true"
ShowColumnChooser="true"
Toolbar="@(new List<string>() { "Add", "Edit", "Delete", "Cancel", "Update", "Search",
"ColumnChooser", "ExcelExport", "PdfExport" })"
Height="100%">
<GridEvents OnToolbarClick="ToolbarClickHandler" TValue="OrderData"></GridEvents>
<GridFilterSettings Type="FilterType.Excel"></GridFilterSettings>
<GridEditSettings AllowAdding="true" AllowEditing="true" AllowDeleting="true"
Mode="EditMode.Dialog"></GridEditSettings>
<GridSelectionSettings Type="SelectionType.Multiple"></GridSelectionSettings>
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" IsPrimaryKey="true" Width="130"
ValidationRules="@(new ValidationRules{ Required=true })"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer Name" Width="200"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight" EditType="EditType.NumericEdit"
Format="C2" Width="160"></GridColumn>
<GridColumn Field="OrderDate" HeaderText="Order Date" Format="MM/dd/yyyy hh:mm tt"
Type="ColumnType.DateTime" EditType="EditType.DateTimePickerEdit" Width="200"></GridColumn>
<GridColumn Field="ShipCountry" HeaderText="Ship Country" Width="170"></GridColumn>
</GridColumns>
</SfGrid>
@code {
private SfGrid<OrderData> Grid;
public List<OrderData> Orders { get; set; }
protected override void OnInitialized()
{
Orders = OrderData.GetAllRecords();
}
public async Task ToolbarClickHandler(Syncfusion.Blazor.Navigations.ClickEventArgs args)
{
if (args.Item.Id == "Grid_pdfexport")
await Grid.ExportToPdfAsync();
if (args.Item.Id == "Grid_excelexport")
await Grid.ExportToExcelAsync();
}
}`AdaptiveUIMode` values:
| Value | Description |
|---|---|
AdaptiveMode.Both | Adaptive layout on mobile and desktop (default) |
AdaptiveMode.Mobile | Adaptive layout on mobile screen sizes only |
TheRowRenderingModeapplied depends on theAdaptiveUIModeconfiguration.
Supported Features in Vertical Mode
When RowRenderingMode="RowDirection.Vertical", the following features are supported:
- Paging (including page size dropdown)
- Sorting
- Filtering
- Selection
- Dialog editing
- Aggregates
- Infinite scrolling
- Toolbar: Add, Filter, Sort, Edit, Delete, Search, toolbar template
- Overflow menu (three-dot icon) shows: ColumnChooser, Print, PdfExport, ExcelExport, CsvExport
The Column Menu feature (grouping, sorting, autofit, filter, column chooser) is only supported when RowRenderingMode is Horizontal.Key Properties
| Property | Type | Description |
|---|---|---|
EnableAdaptiveUI | bool | Enables adaptive mobile-friendly layout |
RowRenderingMode | RowDirection | Horizontal (default) or Vertical row layout |
AdaptiveUIMode | AdaptiveMode | Both (default) or Mobile — controls where adaptive layout applies |
Mobile Layout CSS (Optional)
Use this CSS shell to simulate a mobile device frame in demos or previews:
.e-mobile-layout {
position: relative;
width: 360px;
height: 640px;
margin: auto;
border: 16px solid #f4f4f4;
border-top-width: 60px;
border-bottom-width: 60px;
border-radius: 36px;
box-shadow: 0 0px 2px rgb(144,144,144), 0 0px 10px rgba(0,0,0,0.16);
}
.e-mobile-layout .e-mobile-content {
overflow-x: hidden;
height: 100%;
background: white;
}
/* Simplified adaptive pager */
.e-adaptive-demo .e-pager .e-pagesizes,
.e-adaptive-demo .e-pager .e-pagecountmsg,
.e-adaptive-demo .e-pager .e-pagercontainer {
display: none;
}Aggregates — Syncfusion Blazor DataGrid
Table of Contents
- Basic Aggregate Structure
- Built-in Aggregate Types
- Multiple Aggregate Types on One Column
- Boolean Column Aggregates
- Date Column Aggregates
- Custom Aggregate
- Reactive Aggregates (Batch Editing)
- Notes
Basic Aggregate Structure
Use GridAggregates > GridAggregate > GridAggregateColumns > GridAggregateColumn with a template:
<SfGrid DataSource="@Orders" AllowPaging="true" AllowGrouping="true">
<GridGroupSettings Columns="@(new string[]{ "ShipCountry" })"></GridGroupSettings>
<GridAggregates>
<!-- Footer aggregate -->
<GridAggregate>
<GridAggregateColumns>
<GridAggregateColumn Field="Freight" Type="AggregateType.Sum" Format="C2">
<FooterTemplate>
@{
var agg = context as AggregateTemplateContext;
}
<span>Sum: @agg.Sum</span>
</FooterTemplate>
</GridAggregateColumn>
</GridAggregateColumns>
</GridAggregate>
<!-- Group footer aggregate -->
<GridAggregate>
<GridAggregateColumns>
<GridAggregateColumn Field="Freight" Type="AggregateType.Average" Format="C2">
<GroupFooterTemplate>
@{
var agg = context as AggregateTemplateContext;
}
<span>Avg: @agg.Average</span>
</GroupFooterTemplate>
</GridAggregateColumn>
</GridAggregateColumns>
</GridAggregate>
<!-- Group caption aggregate -->
<GridAggregate>
<GridAggregateColumns>
<GridAggregateColumn Field="Freight" Type="AggregateType.Max" Format="C2">
<GroupCaptionTemplate>
@{
var agg = context as AggregateTemplateContext;
}
<span>Max: @agg.Max</span>
</GroupCaptionTemplate>
</GridAggregateColumn>
</GridAggregateColumns>
</GridAggregate>
</GridAggregates>
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" IsPrimaryKey="true" Width="120"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer" Width="150"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight" Format="C2" TextAlign="TextAlign.Right" Width="120"></GridColumn>
<GridColumn Field="ShipCountry" HeaderText="Ship Country" Width="150"></GridColumn>
</GridColumns>
</SfGrid>Group footer and group caption aggregates appear only when grouping is enabled.
Built-in Aggregate Types
| AggregateType | Description | Access Property |
|---|---|---|
Sum | Sum of numeric values | agg.Sum |
Average | Average of numeric values | agg.Average |
Min | Minimum value | agg.Min |
Max | Maximum value | agg.Max |
Count | Row count | agg.Count |
TrueCount | Count of true boolean values | agg.TrueCount |
FalseCount | Count of false boolean values | agg.FalseCount |
Custom | User-defined calculation | Use template directly |
Multiple Aggregate Types on One Column
Use separate GridAggregate blocks per aggregate:
<GridAggregates>
<GridAggregate>
<GridAggregateColumns>
<GridAggregateColumn Field="Freight" Type="AggregateType.Sum" Format="C2">
<FooterTemplate>
@{ var agg = context as AggregateTemplateContext; }
<span>Sum: @agg.Sum</span>
</FooterTemplate>
</GridAggregateColumn>
</GridAggregateColumns>
</GridAggregate>
<GridAggregate>
<GridAggregateColumns>
<GridAggregateColumn Field="Freight" Type="AggregateType.Max" Format="C2">
<FooterTemplate>
@{ var agg = context as AggregateTemplateContext; }
<span>Max: @agg.Max</span>
</FooterTemplate>
</GridAggregateColumn>
</GridAggregateColumns>
</GridAggregate>
</GridAggregates>Boolean Column Aggregates
<GridAggregateColumn Field="IsActive" Type="AggregateType.TrueCount">
<FooterTemplate>
@{ var agg = context as AggregateTemplateContext; }
<span>Active: @agg.TrueCount</span>
</FooterTemplate>
</GridAggregateColumn>Date Column Aggregates
<GridAggregateColumn Field="OrderDate" Type="AggregateType.Max" Format="d">
<FooterTemplate>
@{ var agg = context as AggregateTemplateContext; }
<span>Latest: @agg.Max</span>
</FooterTemplate>
</GridAggregateColumn>Custom Aggregate
Use AggregateType.Custom when built-in types don't fit:
<GridAggregateColumn Field="ShipCountry" Type="AggregateType.Custom">
<FooterTemplate>
<span>Brazil Orders: @GetBrazilCount()</span>
</FooterTemplate>
</GridAggregateColumn>
@code {
private int GetBrazilCount()
{
return Orders.Count(x => x.ShipCountry == "Brazil");
}
}Reactive Aggregates (Batch Editing)
Aggregates auto-update when editing in EditMode.Batch — no extra configuration needed:
<SfGrid DataSource="@Orders" Toolbar="@(new List<string>{ "Update","Cancel" })">
<GridEditSettings AllowEditing="true" AllowAdding="true" AllowDeleting="true"
Mode="EditMode.Batch">
</GridEditSettings>
<GridAggregates>
<GridAggregate>
<GridAggregateColumns>
<GridAggregateColumn Field="Freight" Type="AggregateType.Sum" Format="C2">
<FooterTemplate>
@{ var agg = context as AggregateTemplateContext; }
<span>Sum: @agg.Sum</span>
</FooterTemplate>
</GridAggregateColumn>
</GridAggregateColumns>
</GridAggregate>
</GridAggregates>
...
</SfGrid>Notes
- With local data: aggregates compute over the entire bound dataset
- With remote data + paging: footer aggregates reflect the current page only (unless the server returns total summaries)
AggregateTemplateContextproperties:Sum,Average,Min,Max,Count,TrueCount,FalseCount- Use
Formatproperty (e.g.,"C2","d") for culture-aware display - Multiple aggregate types for a single column are supported only when one of the aggregate templates is used.
Cell — Syncfusion Blazor DataGrid
Table of Contents
- QueryCellInfo Event
- Custom Attributes
- ClipMode
- Autowrap the Grid Content
- GridLines
- Disable HTML Encoding
- Tooltip
- Tooltip Template
- Custom Tooltip for Columns
- Row Height
QueryCellInfo Event
Customize individual cell rendering at runtime:
<SfGrid DataSource="@Orders">
<GridEvents TValue="Order" QueryCellInfo="CellHandler"></GridEvents>
<GridColumns>
<GridColumn Field="Freight" Width="120"></GridColumn>
</GridColumns>
</SfGrid>
@code {
void CellHandler(QueryCellInfoEventArgs<Order> args)
{
// Change background color for high freight values
if (args.Column.Field == "Freight" && args.Data.Freight > 100)
{
args.Cell.AddStyle(new string[] { "background-color:lightcoral" });
}
}
}Custom Attributes
Apply CSS classes or HTML attributes to columns:
<GridColumn Field="OrderID" CustomAttributes="@(new Dictionary<string,object>{ {\"class\",\"custom-cell\"} })"></GridColumn>Inline Styles in CustomAttributes
Apply inline styles directly to cells using the CustomAttributes property:
<GridColumn Field="ShipCity"
HeaderText="Ship City"
CustomAttributes="@(new Dictionary<string, object>(){ { \"style\", \"background: #d7f0f4; font-style: italic; color: navy\" }})"
Width="100">
</GridColumn>Recommendation: While inline styles work, using CSS classes is preferred for maintainability. Define styles in a <style> block:
<style>
.custom-cell-style {
background: #d7f0f4;
font-style: italic;
color: navy;
}
</style>Then apply via class:
<GridColumn Field="ShipCity"
HeaderText="Ship City"
CustomAttributes="@(new Dictionary<string, object>(){ { \"class\", \"custom-cell-style\" }})"
Width="100">
</GridColumn>ClipMode
Control text overflow behavior:
ClipMode | Behavior |
|---|---|
Clip | Content clipped at cell boundary |
Ellipsis | Shows ... when content overflows |
EllipsisWithTooltip | Shows ... with full value on hover |
<GridColumn Field="ShipName" ClipMode="ClipMode.EllipsisWithTooltip" Width="150"></GridColumn>Autowrap the Grid Content
Enable automatic text wrapping in cells to display multi-line content within defined column widths:
<SfGrid DataSource="@Orders" AllowTextWrap="true" Height="315">
<GridTextWrapSettings WrapMode="WrapMode.Content"></GridTextWrapSettings>
<GridColumns>
<GridColumn Field="Name" HeaderText="Name" Width="70"></GridColumn>
<GridColumn Field="Description" HeaderText="Description" Width="120"></GridColumn>
</GridColumns>
</SfGrid>WrapMode Options:
| Mode | Description |
|---|---|
Both | Wraps text in both header and content cells (default) |
Header | Wraps text only in header cells |
Content | Wraps text only in content cells |
Key Points:
- Set
AllowTextWrapto true to enable wrapping - Define column widths to control wrap boundaries
- Use
TextWrapSettings.WrapModeto customize wrapping behavior - HTML content may interfere with wrapping; use templates for complex content
GridLines
Control cell border visibility:
<SfGrid DataSource="@Orders" GridLines="GridLine.Both">
...
</SfGrid>GridLine values: Default, Both, None, Horizontal, Vertical.
Disable HTML Encoding
Render raw HTML in cells (use with trusted data only):
<GridColumn Field="Description" DisableHtmlEncode="false"></GridColumn>Warning: Only disable HTML encoding for trusted data sources to avoid XSS vulnerabilities.
Tooltip
Display tooltips on cell hover showing the cell value:
<SfGrid DataSource="@Orders" ShowTooltip="true">
<GridColumns>
<GridColumn Field="ShipName" HeaderText="Ship Name" Width="150"></GridColumn>
</GridColumns>
</SfGrid>Use the grid-levelShowTooltipproperty to enable tooltips for all cells. For advanced tooltip customization with custom content, use theTooltipTemplateproperty withinGridTemplates.
Tooltip Template
Customize tooltip content for header and content cells using the TooltipTemplate property:
<SfGrid DataSource="@Orders" ShowTooltip="true" Width="700">
<GridTemplates>
<TooltipTemplate>
@{
var tooltip = context as TooltipTemplateContext;
var order = tooltip?.Data as OrderData;
if (tooltip?.RowIndex == -1)
{
// Header cell tooltip
<span><strong>@tooltip.Value</strong>: Column information</span>
}
else
{
// Content cell tooltip
var fieldName = tooltip?.Column?.Field;
if (fieldName == nameof(OrderData.Freight))
{
<p><strong>Freight Cost: </strong>$@order.Freight</p>
}
else if (fieldName == nameof(OrderData.ShipCity))
{
<p><strong>Destination: </strong>@order.ShipCity, @order.ShipCountry</p>
}
else
{
<span>@tooltip.Value</span>
}
}
}
</TooltipTemplate>
</GridTemplates>
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" Width="90"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer ID" Width="90"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight" Format="C2" Width="80"></GridColumn>
<GridColumn Field="ShipCity" HeaderText="Ship City" Width="100"></GridColumn>
</GridColumns>
</SfGrid>TooltipTemplateContext Properties:
| Property | Type | Description |
|---|---|---|
Value | string | Cell content (column name for header, cell value for content) |
RowIndex | int | Row index (-1 for header cells) |
ColumnIndex | int | Column index |
Data | object | Complete row data (null for header cells) |
Column | GridColumn | Column metadata including field name |
Custom Tooltip for Columns
Display custom tooltips using the SfTooltip component within column templates:
@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor.Popups
<SfGrid DataSource="@Orders">
<GridColumns>
<GridColumn Field="EmployeeID" HeaderText="Employee ID" TextAlign="TextAlign.Right" Width="120"></GridColumn>
<GridColumn Field="FirstName" HeaderText="First Name" Width="130">
<Template>
@{
var employee = (context as EmployeeData);
<SfTooltip Position="Position.BottomLeft">
<ContentTemplate>
<span>Employee: @employee.FirstName @employee.LastName</span>
</ContentTemplate>
<ChildContent>
<span>@employee.FirstName</span>
</ChildContent>
</SfTooltip>
}
</Template>
</GridColumn>
<GridColumn Field="Title" HeaderText="Title" Width="120"></GridColumn>
<GridColumn Field="HireDate" HeaderText="Hire Date" Format="d" TextAlign="TextAlign.Right" Width="150"></GridColumn>
</GridColumns>
</SfGrid>
@code {
public List<EmployeeData> Orders { get; set; }
protected override void OnInitialized()
{
Orders = EmployeeData.GetAllRecords();
}
}Key Advantages:
- Rich HTML content support in tooltips
- Flexible positioning with
Positionproperty - Multiple templates per column possible
- Can display complex data relationships
- Better user experience for detailed information
Row Height
Control default row height at grid level or per-row:
<SfGrid DataSource="@Orders" RowHeight="40">
...
</SfGrid>Per-row height via RowDataBound:
<GridEvents TValue="Order" RowDataBound="RowBound"></GridEvents>
@code {
void RowBound(RowDataBoundEventArgs<Order> args)
{
if (args.Data.Freight > 100)
args.Row.AddStyle(new string[] { "height:60px" });
}
}
Clipboard, AutoFill & Paste — Syncfusion Blazor DataGrid
Table of Contents
- Overview
- Clipboard — Copy Selected Rows or Cells
- Programmatic Copy via External Button
- AutoFill
- AutoFill Limitations
- Paste
- Paste Limitations
Overview
The clipboard feature allows copying selected rows or cells to the clipboard using keyboard shortcuts or programmatic methods. AutoFill lets users drag a handle to fill adjacent cells. Paste lets users copy cells and paste them to a different range within the grid.
---
Clipboard — Copy Selected Rows or Cells
Enable selection and focus the grid to use keyboard shortcuts:
| Windows | Mac | Action |
|---|---|---|
Ctrl + C | Command + C | Copy selected rows or cells |
Ctrl + Shift + H | Command + Shift + H | Copy with column headers |
If Mode is Row, entire rows are copied. If Mode is Cell, only highlighted cells are copied.
<SfGrid DataSource="@Orders" Height="348">
<GridSelectionSettings Type="SelectionType.Multiple"></GridSelectionSettings>
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" IsPrimaryKey="true" Width="120" />
<GridColumn Field="CustomerID" HeaderText="Customer ID" Width="150" />
<GridColumn Field="ShipCity" HeaderText="Ship City" Width="150" />
<GridColumn Field="ShipName" HeaderText="Ship Name" Width="150" />
</GridColumns>
</SfGrid>Programmatic Copy via External Button
Use CopyAsync() to trigger clipboard copy programmatically:
<SfButton OnClick="Copy">Copy</SfButton>
<SfButton OnClick="CopyHeader">Copy With Header</SfButton>
<SfGrid @ref="Grid" DataSource="@Orders" Height="348">
<GridColumns>...</GridColumns>
</SfGrid>
@code {
SfGrid<Order> Grid;
async Task Copy() => await Grid.CopyAsync();
// Pass true to include column headers in copied content
async Task CopyHeader() => await Grid.CopyAsync(true);
}---
AutoFill
AutoFill lets users copy values from selected cells and drag a handle to fill adjacent cells.
Requirements:
EnableAutoFill="true"on the grid- Cell selection:
Mode="SelectionMode.Cell",CellSelectionMode="CellSelectionMode.Box",Type="SelectionType.Multiple" - Batch editing enabled:
Mode="EditMode.Batch"
<SfGrid DataSource="@Orders" EnableAutoFill="true" AllowSelection="true"
Toolbar="@(new List<string> { "Add", "Update", "Cancel" })" Height="348">
<GridSelectionSettings CellSelectionMode="CellSelectionMode.Box"
Mode="SelectionMode.Cell"
Type="SelectionType.Multiple">
</GridSelectionSettings>
<GridEditSettings AllowAdding="true" AllowDeleting="true"
AllowEditing="true" Mode="EditMode.Batch">
</GridEditSettings>
<GridColumns>
<GridColumn Field="OrderID" IsPrimaryKey="true" Width="120" />
<GridColumn Field="CustomerID" Width="150" />
<GridColumn Field="ShipCity" Width="150" />
</GridColumns>
</SfGrid>Usage: 1. Select the source cells. 2. Hover over the bottom-right corner to reveal the autofill handle. 3. Drag the handle to the target cells and release.
AutoFill Limitations
| Limitation | Detail |
|---|---|
| Data type conversion | Strings into numeric/date cells produce NaN or empty |
| Sequential series | Copies values directly — no series generation |
| Virtualization | Not supported with virtual or column virtualization |
| Infinite scrolling | Only applies to cells within the current viewport |
AutoFill is not compatible with AllowDragSelection.---
Paste
Paste copies selected cells to a new range using Ctrl + C / Ctrl + V.
Requirements: Same as AutoFill — cell selection with Box mode and Batch editing.
<SfGrid DataSource="@Orders" EnableAutoFill="true" AllowSelection="true"
Toolbar="@(new List<string> { "Add", "Update", "Cancel" })" Height="348">
<GridSelectionSettings CellSelectionMode="CellSelectionMode.Box"
Mode="SelectionMode.Cell"
Type="SelectionType.Multiple">
</GridSelectionSettings>
<GridEditSettings AllowAdding="true" AllowDeleting="true"
AllowEditing="true" Mode="EditMode.Batch">
</GridEditSettings>
<GridColumns>
<GridColumn Field="OrderID" IsPrimaryKey="true" Visible="false" Width="120" />
<GridColumn Field="CustomerID" Width="150" />
<GridColumn Field="ShipCity" Width="150" />
</GridColumns>
</SfGrid>Steps: 1. Select cells to copy → Ctrl + C 2. Select target cells → Ctrl + V
Paste Limitations
- Pasting strings into numeric cells results in
NaN; into date cells results in an empty cell. - Ensure pasted values are compatible with the target column's data type.
Column Chooser — Syncfusion Blazor DataGrid
Table of Contents
1. Enable Column Chooser 2. Hide Column in Chooser 3. Open Chooser Programmatically 4. Customize Chooser Dialog 5. Search Operator
---
Enable Column Chooser
Enable the column chooser feature by setting ShowColumnChooser to true:
<SfGrid DataSource="@Orders" ShowColumnChooser="true"
Toolbar="@(new List<string>() { "ColumnChooser" })">
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" Width="120"></GridColumn>
<GridColumn Field="OrderDate" HeaderText="Order Date" Format="d" Width="130"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight" Format="C2" Width="120"></GridColumn>
<GridColumn Field="ShipCountry" HeaderText="Ship Country" Width="120"></GridColumn>
<GridColumn Field="ShipCity" HeaderText="Ship City" Visible="false" Width="120"></GridColumn>
</GridColumns>
</SfGrid>Features:
- Dialog displays column names
- Show/hide columns dynamically
- Search functionality to find columns
- Header text displayed as column name
The column chooser dialog displays the header text of each column by default. If HeaderText is not defined, the Field name is shown instead.
---
Hide Column in Chooser
Prevent specific columns from appearing in the column chooser using ShowInColumnChooser:
<SfGrid DataSource="@Orders" ShowColumnChooser="true"
Toolbar="@(new List<string>() { "ColumnChooser" })">
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID"
ShowInColumnChooser="false" Width="120"></GridColumn>
<GridColumn Field="OrderDate" HeaderText="Order Date" Format="d" Width="130"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight" Format="C2" Width="120"></GridColumn>
<GridColumn Field="ShipCountry" HeaderText="Ship Country" Width="120"></GridColumn>
</GridColumns>
</SfGrid>Use cases:
- Keep primary key columns visible
- Prevent accidental column hiding
- Simplify dialog for users
- Hide system/internal columns
---
Open Chooser Programmatically
Open the column chooser dialog using code via the OpenColumnChooserAsync method:
<SfButton OnClick="Show">Open Column Chooser</SfButton>
<SfGrid @ref="Grid" DataSource="@Orders" ShowColumnChooser="true">
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" Width="120"></GridColumn>
<GridColumn Field="OrderDate" HeaderText="Order Date" Width="130"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight" Width="120"></GridColumn>
<GridColumn Field="ShipCountry" HeaderText="Ship Country" Width="120"></GridColumn>
</GridColumns>
</SfGrid>
@code {
private SfGrid<OrderData> Grid;
public void Show()
{
// Open at position (100, 40)
Grid.OpenColumnChooserAsync(100, 40);
}
}Method parameters:
- x (double): Horizontal position
- y (double): Vertical position
---
Customize Chooser Dialog
Customize the column chooser dialog size and appearance using CSS:
<SfGrid DataSource="@Orders" ShowColumnChooser="true">
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" Width="120"></GridColumn>
<GridColumn Field="OrderDate" HeaderText="Order Date" Width="130"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight" Width="120"></GridColumn>
</GridColumns>
</SfGrid>
<style>
.e-grid .e-dialog.e-ccdlg {
max-height: 600px !important;
width: 300px !important;
}
.e-grid .e-ccdlg .e-cc-contentdiv {
height: 250px !important;
width: 250px !important;
}
</style>Customizable selectors:
.e-dialog.e-ccdlg: Main dialog container.e-cc-contentdiv: Dialog content area- Use
!importantto override default styles
---
Search Operator
Change the default search operator in the column chooser using GridColumnChooserSettings:
<SfGrid DataSource="@Orders" ShowColumnChooser="true"
Toolbar="@(new List<string>() { "ColumnChooser" })">
<GridColumnChooserSettings Operator="Syncfusion.Blazor.Operator.Contains"></GridColumnChooserSettings>
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" Width="120"></GridColumn>
<GridColumn Field="OrderDate" HeaderText="Order Date" Width="130"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight" Width="120"></GridColumn>
<GridColumn Field="ShipCountry" HeaderText="Ship Country" Width="120"></GridColumn>
</GridColumns>
</SfGrid>Available operators:
- StartsWith: Match columns beginning with search text (default)
- EndsWith: Match columns ending with search text
- Contains: Match columns containing search text
- Equal: Match exact column names
Default behavior:
- Search uses StartsWith operator
- Users can find columns by typing column names
- Real-time filtering of column list
Column Headers — Syncfusion Blazor DataGrid
Table of Contents
1. Header Text 2. Header Template 3. Stacked Headers 4. Header Text Alignment 5. Auto-wrap Header Text
---
Header Text
Override the default header text displayed from the Field value using the HeaderText property:
<GridColumn Field="CustomerID" HeaderText="Customer Name" Width="150"></GridColumn>
<GridColumn Field="OrderDate" HeaderText="Order Date" Format="d" Width="130"></GridColumn>IfHeaderTextis not defined, the column'sFieldvalue is used as the header text.
---
Header Template
Customize the header element using the HeaderTemplate property to render custom HTML or Blazor components:
<GridColumn Field="CustomerID" HeaderText="Customer Name">
<HeaderTemplate>
<div>
<span class="e-icons e-user" style="font-size:14px"></span>
Customer
</div>
</HeaderTemplate>
</GridColumn>Header templates support:
- Custom HTML elements
- Blazor components
- Icons and dropdowns
- Switches and interactive controls
The HeaderTemplate property is applicable only to columns that have a header element. Any HTML or Blazor component can be used in the header template.---
Stacked Headers
Group multiple columns under a common header by nesting GridColumn directives:
<GridColumns>
<GridColumn HeaderText="Order Details" TextAlign="TextAlign.Center">
<ChildContent>
<GridColumns>
<GridColumn Field="OrderDate" HeaderText="Order Date" Width="130" Format="d"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight ($)" Width="135" Format="C2"></GridColumn>
</GridColumns>
</ChildContent>
</GridColumn>
<GridColumn HeaderText="Ship Details" TextAlign="TextAlign.Center">
<ChildContent>
<GridColumns>
<GridColumn Field="ShipCity" HeaderText="Ship City" Width="140"></GridColumn>
<GridColumn Field="ShipCountry" HeaderText="Ship Country" Width="140"></GridColumn>
</GridColumns>
</ChildContent>
</GridColumn>
</GridColumns>Benefits:
- Better data organization
- Improved readability
- Structured column grouping
---
Header Text Alignment
Align header text horizontally using the HeaderTextAlign property:
<GridColumn Field="OrderID" HeaderText="Order ID" HeaderTextAlign="TextAlign.Right" Width="120"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer ID" HeaderTextAlign="TextAlign.Center" Width="150"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight" HeaderTextAlign="TextAlign.Right" Format="C2" Width="120"></GridColumn>Alignment options:
- Left: Aligns the text to the left (default)
- Center: Aligns the text to the center
- Right: Aligns the text to the right
- Justify: Justifies the header text
TheHeaderTextAlignproperty only changes the alignment of header text, not the cell content. UseTextAlignto align cell content andHeaderTextAlignfor header alignment.
---
Auto-wrap Header Text
Enable text wrapping for header text when it exceeds column width using AllowTextWrap property:
<SfGrid DataSource="@Orders" AllowTextWrap="true">
<GridTextWrapSettings WrapMode="WrapMode.Header"></GridTextWrapSettings>
<GridColumns>
<GridColumn Field="Inventor" HeaderText="Inventor Name" Width="70"></GridColumn>
<GridColumn Field="PatentFamilies" HeaderText="Number of Patent Families" Width="80"></GridColumn>
<GridColumn Field="Invention" HeaderText="Main Fields Of Invention" Width="120"></GridColumn>
</GridColumns>
</SfGrid>Wrap mode options:
- Both: Wraps both header text and content (default)
- Header: Wraps only header text
- Content: Wraps only content
Specify appropriate column widths using the Width property to ensure proper wrapping. Header text without white space does not wrap.Column Menu — Syncfusion Blazor DataGrid
Table of Contents
1. Enable Column Menu 2. Default Menu Items 3. Disable Menu for Specific Column 4. Add Custom Menu Items 5. Handle Menu Item Click 6. Customize Menu Items
---
Enable Column Menu
Enable the column menu by setting ShowColumnMenu to true:
<SfGrid DataSource="@Orders" Height="315" AllowGrouping="true" AllowSorting="true"
AllowFiltering="true" ShowColumnMenu="true">
<GridFilterSettings Type="FilterType.CheckBox"></GridFilterSettings>
<GridGroupSettings ShowGroupedColumn="true"></GridGroupSettings>
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" Width="120"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer Name" Width="150"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight" Format="C2" Width="120"></GridColumn>
<GridColumn Field="ShipCity" HeaderText="Ship City" Width="120"></GridColumn>
</GridColumns>
</SfGrid>Result:
- Click menu icon in column header to open contextual menu
- Quick access to sorting, filtering, and other operations
---
Default Menu Items
The column menu provides these built-in operations:
| Item | Function |
|---|---|
| SortAscending | Sort column in ascending order |
| SortDescending | Sort column in descending order |
| Group | Group data by this column |
| Ungroup | Remove grouping for this column |
| AutoFit | Adjust column width to fit content |
| AutoFitAll | Adjust all columns to fit content |
| ColumnChooser | Open column visibility dialog |
| Filter | Display filter options for column |
---
Disable Menu for Specific Column
Prevent the column menu from appearing for specific columns:
<SfGrid DataSource="@Orders" Height="315" ShowColumnMenu="true">
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID"
ShowColumnMenu="false" Width="100"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer Name" Width="100"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight" Format="C2" Width="100"></GridColumn>
<GridColumn Field="ShipCity" HeaderText="Ship City" Width="100"></GridColumn>
</GridColumns>
</SfGrid>Use cases:
- Protect primary key columns
- Prevent customization of critical columns
- Simplify menu for certain columns
---
Add Custom Menu Items
Add custom items to the column menu using ColumnMenuItems:
<SfGrid @ref="Grid" DataSource="@Orders" Height="315"
ColumnMenuItems="@MenuItems" ShowColumnMenu="true"
AllowGrouping="true" AllowSorting="true">
<GridEvents ColumnMenuItemClicked="ColumnMenuItemClickedHandler" TValue="OrderData"></GridEvents>
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" Width="100"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer Name" Width="120"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight" Format="C2" Width="100"></GridColumn>
</GridColumns>
</SfGrid>
@code {
private SfGrid<OrderData> Grid;
public List<ColumnMenuItemModel> MenuItems = new List<ColumnMenuItemModel>
{
new ColumnMenuItemModel { Text = "Clear Sorting", Id = "clearSort" },
new ColumnMenuItemModel { Text = "Clear Grouping", Id = "clearGroup" }
};
public void ColumnMenuItemClickedHandler(ColumnMenuClickEventArgs args)
{
switch (args.Item.Id)
{
case "clearSort":
Grid.ClearSortingAsync();
break;
case "clearGroup":
Grid.ClearGroupingAsync();
break;
}
}
}Custom menu features:
- Define unique menu items
- Assign ID to identify items
- Handle clicks via events
---
Handle Menu Item Click
Handle column menu item clicks using the ColumnMenuItemClicked event:
<SfGrid @ref="Grid" DataSource="@Orders" ShowColumnMenu="true">
<GridEvents ColumnMenuItemClicked="OnMenuItemClicked" TValue="OrderData"></GridEvents>
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" Width="100"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer ID" Width="120"></GridColumn>
</GridColumns>
</SfGrid>
@code {
private SfGrid<OrderData> Grid;
public void OnMenuItemClicked(ColumnMenuClickEventArgs args)
{
// Access menu item information
var menuId = args.Item.Id;
var columnField = args.Column.Field;
var columnText = args.Column.HeaderText;
// Handle custom logic
if (menuId == "customAction")
{
// Perform custom action
}
}
}Event arguments:
- Item: The clicked menu item
- Column: The column on which menu was opened
- Access item properties: Text, Id
- Access column properties: Field, HeaderText, Width
---
Customize Menu Items
Hide or customize menu items for specific columns using OnColumnMenuOpen event:
<SfGrid @ref="Grid" DataSource="@Orders" ShowColumnMenu="true">
<GridEvents OnColumnMenuOpen="OnColumnMenuOpenHandler" TValue="OrderData"></GridEvents>
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" Width="120"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer ID" Width="150"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight" Width="120"></GridColumn>
</GridColumns>
</SfGrid>
@code {
public void OnColumnMenuOpenHandler(ColumnMenuOpenEventArgs args)
{
foreach (var item in args.Items)
{
// Hide Filter option for OrderID column
if (item.Text == "Filter" && args.Column.Field == "OrderID")
{
item.Hidden = true;
}
}
}
}Customization options:
- Show/hide items conditionally
- Disable items based on column
- Modify item properties
- Control menu behavior per column
Column Rendering — Syncfusion Blazor DataGrid
Table of Contents
1. Define Columns Manually 2. Auto-Generated Columns 3. Configure Primary Key 4. Configure Column Options 5. Column Field Binding
---
Define Columns Manually
Manually define columns using GridColumn to specify each column and configure properties:
<SfGrid DataSource="@Orders">
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID"
TextAlign="TextAlign.Right" Width="120"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer ID"
Width="150"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight" Format="C2"
TextAlign="TextAlign.Right" Width="120"></GridColumn>
<GridColumn Field="OrderDate" HeaderText="Order Date" Format="d"
Type="ColumnType.Date" Width="130"></GridColumn>
</GridColumns>
</SfGrid>Benefits:
- Full control over column behavior
- Customize properties individually
- Define sorting, filtering, and editing rules
- Set specific data types and formats
---
Auto-Generated Columns
When no GridColumns block is defined, columns are automatically generated from the DataSource:
<SfGrid DataSource="@Orders">
<!-- No GridColumns block — columns auto-generated from Order properties -->
</SfGrid>How it works:
- All properties in DataSource become columns
- Column type inferred from first record
- Default header text is property name
- Operations like sorting and filtering enabled automatically
When columns are auto-generated, the columnTypeis determined from the first record of theDataSource. For large datasets, auto-generating columns can impact performance.
---
Configure Primary Key
Set a primary key for auto-generated columns using the OnDataBound event:
<SfGrid @ref="Grid" DataSource="@Orders" AllowPaging="true">
<GridEditSettings AllowEditing="true" AllowAdding="true" AllowDeleting="true"></GridEditSettings>
<GridEvents OnDataBound="DataBoundHandler" TValue="OrderData"></GridEvents>
</SfGrid>
@code {
private SfGrid<OrderData> Grid;
public void DataBoundHandler(BeforeDataBoundArgs<OrderData> args)
{
// Set first column as primary key
Grid.Columns[0].IsPrimaryKey = true;
}
}Why it's needed:
- Uniquely identify rows for CRUD operations
- Required when editing is enabled
- Enables update and delete functionality
---
Configure Column Options
Apply column options like Type, Format, and Width to auto-generated columns:
<SfGrid @ref="Grid" DataSource="@Orders">
<GridEvents OnDataBound="DataBoundHandler" TValue="OrderData"></GridEvents>
</SfGrid>
@code {
private SfGrid<OrderData> Grid;
public void DataBoundHandler(BeforeDataBoundArgs<OrderData> args)
{
var gridColumns = Grid.Columns;
foreach (var column in gridColumns)
{
if (column.Field == "OrderID")
{
column.Width = "200";
column.Type = ColumnType.Integer;
}
else if (column.Field == "OrderDate")
{
column.Type = ColumnType.Date;
column.Format = "d";
}
else if (column.Field == "Freight")
{
column.Format = "C2";
column.TextAlign = TextAlign.Right;
}
}
}
}Configurable properties:
- Type: ColumnType (String, Number, Date, DateTime, Boolean)
- Format: Display format (C2, d, N2, etc.)
- Width: Column width
- TextAlign: Text alignment
- HeaderText: Custom header text
---
Column Field Binding
The Field property maps DataSource values to Grid columns:
<GridColumn Field="OrderID" HeaderText="Order ID" Width="120"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer" Width="150"></GridColumn>Field binding rules:
- Required for CRUD operations: Field must match DataSource property name
- Not needed for template-only columns: Pure display columns can omit Field
- Complex binding supported: Use dot notation for nested properties
- Case-sensitive: Field name must match exactly
<!-- Simple binding -->
<GridColumn Field="CustomerID"></GridColumn>
<!-- Complex binding (nested properties) -->
<GridColumn Field="Employee.Name"></GridColumn>
<GridColumn Field="Address.City"></GridColumn>If the columnFieldis not present in theDataSource, the column will display empty values. If theFieldname contains a dot operator, it is treated as complex binding.
Column Reorder — Syncfusion Blazor DataGrid
Table of Contents
1. Enable Column Reordering 2. Prevent Reordering 3. Programmatic Reordering 4. Reorder by Index 5. Reorder by Field
---
Enable Column Reordering
Enable column reordering by setting the AllowReordering property to true:
<SfGrid DataSource="@Orders" Height="315" AllowReordering="true">
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" Width="100"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer ID" Width="100"></GridColumn>
<GridColumn Field="ShipCity" HeaderText="Ship City" Width="100"></GridColumn>
<GridColumn Field="ShipName" HeaderText="Ship Name" Width="120"></GridColumn>
</GridColumns>
</SfGrid>Features:
- Drag and drop column headers to reorder
- Visual feedback during drag operation
- Column data position updates with header
---
Prevent Reordering
Disable reordering for specific columns by setting AllowReordering to false:
<SfGrid DataSource="@Orders" Height="315" AllowReordering="true">
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" Width="100"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer ID" Width="100"></GridColumn>
<GridColumn Field="ShipCity" HeaderText="Ship City" AllowReordering="false" Width="100"></GridColumn>
<GridColumn Field="ShipName" HeaderText="Ship Name" Width="120"></GridColumn>
</GridColumns>
</SfGrid>Use cases:
- Keep primary key columns fixed
- Prevent accidental reordering of critical columns
- Maintain standard column layout
When columns are reordered, the position of the corresponding column data also changes. Ensure that any logic dependent on column order is updated accordingly.
---
Programmatic Reordering
Reorder columns programmatically using methods instead of drag-and-drop:
<SfButton OnClick="ReorderByIndex">Reorder by Index</SfButton>
<SfButton OnClick="ReorderByField">Reorder by Field</SfButton>
<SfGrid @ref="Grid" DataSource="@Orders" Height="315" AllowReordering="true">
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" Width="100"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer ID" Width="100"></GridColumn>
<GridColumn Field="ShipCity" HeaderText="Ship City" Width="100"></GridColumn>
<GridColumn Field="ShipName" HeaderText="Ship Name" Width="120"></GridColumn>
</GridColumns>
</SfGrid>
@code {
private SfGrid<OrderData> Grid;
public async Task ReorderByIndex()
{
// Move column at index 1 to index 3
await Grid.ReorderColumnByIndexAsync(1, 3);
}
public async Task ReorderByField()
{
// Move OrderID column to index 2
await Grid.ReorderColumnByTargetIndexAsync("OrderID", 2);
}
}Available methods:
- ReorderColumnByIndexAsync(fromIndex, toIndex): Reorder by current and target index
- ReorderColumnByTargetIndexAsync(fieldName, toIndex): Reorder by field name
---
Reorder by Index
Move columns using their index positions:
@code {
public async Task MoveColumnToPosition()
{
// fromIndex: current position (0-based)
// toIndex: target position (0-based)
await Grid.ReorderColumnByIndexAsync(0, 2);
}
}Parameters:
- fromIndex (int): Current index of the column to move
- toIndex (int): Target index where column should be placed
---
Reorder by Field
Move columns using their field names:
@code {
public async Task MoveColumnByName()
{
// Move CustomerID column to index 0 (first position)
await Grid.ReorderColumnByTargetIndexAsync("CustomerID", 0);
// Move ShipCity column to index 3
await Grid.ReorderColumnByTargetIndexAsync("ShipCity", 3);
}
}Parameters:
- fieldName (string): Field name of the column to move
- toIndex (int): Target index where column should be placed
Benefits:
- Clear intent using field names
- No need to track index changes
- More maintainable code
Column Resizing — Syncfusion Blazor DataGrid
Table of Contents
1. Enable Column Resizing 2. Min and Max Width 3. Prevent Resizing 4. AutoFit Columns 5. Resize Events
---
Enable Column Resizing
Enable column resizing by setting the AllowResizing property to true:
<SfGrid DataSource="@Orders" AllowResizing="true">
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" Width="100"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer ID" Width="120"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight" Format="C2" Width="100"></GridColumn>
</GridColumns>
</SfGrid>Behavior:
- Click and drag the right edge of column header to resize
- Column width adjusts immediately during drag operation
- In RTL mode, drag the left edge of the header cell
---
Min and Max Width
Restrict column resizing between minimum and maximum width values:
<SfGrid DataSource="@Orders" AllowResizing="true">
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID"
MinWidth="100" MaxWidth="250" Width="120"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer ID"
MinWidth="120" MaxWidth="300" Width="150"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight"
MinWidth="80" MaxWidth="200" Width="100"></GridColumn>
</GridColumns>
</SfGrid>Properties:
- MinWidth: Minimum allowed column width (in pixels)
- MaxWidth: Maximum allowed column width (in pixels)
- When resizing exceeds the range, width is automatically restricted to the nearest valid value
TheMinWidthandMaxWidthproperties are applied only during column resizing, not when resizing the browser window.
---
Prevent Resizing
Disable resizing for specific columns by setting AllowResizing to false:
<SfGrid DataSource="@Orders" AllowResizing="true">
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" Width="100"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer ID"
AllowResizing="false" Width="120"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight" Width="100"></GridColumn>
</GridColumns>
</SfGrid>Column-level configuration:
- Override grid-level resizing for specific columns
- Prevent accidental width changes
- Maintain fixed-width columns
---
AutoFit Columns
Automatically adjust column widths to fit content using the AutoFitColumnsAsync method:
<SfGrid @ref="Grid" DataSource="@Orders">
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" Width="100"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer ID" Width="120"></GridColumn>
<GridColumn Field="ShipName" HeaderText="Ship Name" Width="150"></GridColumn>
</GridColumns>
</SfGrid>
@code {
private SfGrid<OrderData> Grid;
// AutoFit all columns
public async Task AutoFitAllColumns()
{
await Grid.AutoFitColumnsAsync();
}
// AutoFit specific columns
public async Task AutoFitSpecificColumns()
{
await Grid.AutoFitColumnsAsync(new string[] { "OrderID", "ShipName" });
}
}AutoFit options:
- All columns:
AutoFitColumnsAsync()- no parameters - Specific columns:
AutoFitColumnsAsync(string[])- pass array of field names
Use cases:
- Initial grid rendering with varying content
- Dynamic data updates
- Content-based layout adjustment
---
Resize Events
Handle column resizing events:
<SfGrid DataSource="@Orders" AllowResizing="true">
<GridEvents OnResizeStart="OnResizeStart" ResizeStopped="ResizeStopped"
TValue="OrderData"></GridEvents>
<GridColumns>
<GridColumn Field="OrderID" Width="100"></GridColumn>
<GridColumn Field="CustomerID" Width="120"></GridColumn>
</GridColumns>
</SfGrid>
@code {
private void OnResizeStart(ResizeStartEventArgs args)
{
// Triggered before resizing starts
// Can cancel resizing by setting args.Cancel = true
}
private void ResizeStopped(ResizeStoppedEventArgs args)
{
// Triggered after resizing completes
// Access the new column width via args
}
}Available events:
- OnResizeStart: Fired before resizing begins (cancelable)
- ResizeStopped: Fired after resizing completes
Column Spanning — Syncfusion Blazor DataGrid
Table of Contents
1. AutoSpan Modes 2. Enable Column Spanning 3. Disable Spanning for Specific Column 4. Row vs Column Spanning
---
AutoSpan Modes
The DataGrid provides automatic cell merging options through the AutoSpan property:
| Mode | Description |
|---|---|
AutoSpanMode.None | Disables cell spanning (default) |
AutoSpanMode.Row | Enables horizontal merging across columns within same row |
AutoSpanMode.Column | Enables vertical merging of adjacent cells with identical values |
AutoSpanMode.HorizontalAndVertical | Enables both horizontal and vertical merging |
---
Enable Column Spanning
Enable vertical cell merging for identical values in the same column:
<SfGrid DataSource="@EmployeeTimeSheet"
GridLines="GridLine.Both"
AutoSpan="AutoSpanMode.Column"
AllowSelection="false"
EnableHover="false">
<GridColumns>
<GridColumn Field="EmployeeID" HeaderText="Employee ID" Width="150" TextAlign="TextAlign.Right"></GridColumn>
<GridColumn Field="EmployeeName" HeaderText="Employee Name" Width="180"></GridColumn>
<GridColumn Field="Time_9_00" HeaderText="9:00 AM" Width="150" TextAlign="TextAlign.Center"></GridColumn>
<GridColumn Field="Time_9_30" HeaderText="9:30 AM" Width="150" TextAlign="TextAlign.Center"></GridColumn>
<GridColumn Field="Time_10_00" HeaderText="10:00 AM" Width="150" TextAlign="TextAlign.Center"></GridColumn>
</GridColumns>
</SfGrid>How it works:
- Grid automatically merges stacked cells with identical values
- Reduces visual redundancy
- Provides cleaner, more structured layout
- Requires no additional code
Use cases:
- Timesheet data with repeated activities
- Task tracking across time periods
- Status columns with repeated values
---
Disable Spanning for Specific Column
Override grid-level spanning for individual columns:
<SfGrid DataSource="@EmployeeTimeSheet"
AutoSpan="AutoSpanMode.Column"
GridLines="GridLine.Both">
<GridColumns>
<GridColumn Field="EmployeeID" HeaderText="Employee ID" Width="150"></GridColumn>
<GridColumn Field="EmployeeName" HeaderText="Employee Name" Width="180"></GridColumn>
<GridColumn Field="Time_9_00" HeaderText="9:00 AM" Width="150"></GridColumn>
<GridColumn Field="Time_9_30" HeaderText="9:30 AM" Width="150" AutoSpan="AutoSpanMode.None"></GridColumn>
<GridColumn Field="Time_10_00" HeaderText="10:00 AM" Width="150"></GridColumn>
<GridColumn Field="Time_10_30" HeaderText="10:30 AM" Width="150" AutoSpan="AutoSpanMode.None"></GridColumn>
</GridColumns>
</SfGrid>Column-level property:
- Set
AutoSpan="AutoSpanMode.None"on GridColumn - Overrides grid-level AutoSpan setting
- Provides precise control over which columns merge
Benefits:
- Exclude specific columns from spanning
- Maintain standard display for certain data
- Mix spanning and non-spanning columns
---
Row vs Column Spanning
Different spanning modes provide different merging behaviors:
Column Spanning (Vertical)
Merges cells vertically when identical values appear in consecutive rows:
<SfGrid DataSource="@Orders" AutoSpan="AutoSpanMode.Column">
<!-- Identical values in same column are merged vertically -->
</SfGrid>Result:
├─ Employee 1 ──┐ Same Employee ID
│ │ merged vertically
├─ Employee 1 ──┤
│ │
├─ Employee 2 ──┤Row Spanning (Horizontal)
Merges cells horizontally across columns in the same row:
<SfGrid DataSource="@Orders" AutoSpan="AutoSpanMode.Row">
<!-- Identical values in same row are merged horizontally -->
</SfGrid>Horizontal and Vertical
Combines both vertical and horizontal merging:
<SfGrid DataSource="@Orders" AutoSpan="AutoSpanMode.HorizontalAndVertical">
<!-- Executes row merging first, then column merging -->
</SfGrid>Choose based on data structure:
- Column: For repeated values down rows (timesheets, activities)
- Row: For repeated values across columns
- HorizontalAndVertical: For complex data with both types of repetition
Column Template — Syncfusion Blazor DataGrid
Table of Contents
1. Render HTML Elements 2. Render Image in Column 3. Render Hyperlink in Column 4. Render Components in Column 5. Render DropDownList 6. Render Chip 7. Render ProgressBar
---
Render HTML Elements
The Template property allows rendering custom HTML elements or Blazor components instead of the default field value:
<GridColumn HeaderText="Custom Content" Width="200">
<Template>
@{
var data = (context as OrderData);
<div class="custom-cell">
<strong>@data.OrderID</strong>
</div>
}
</Template>
</GridColumn>Template columns are primarily intended for rendering custom content and do not provide built-in support for sorting, filtering, or editing. Define the Field property for a Template column to enable CRUD and data operations.---
Render Image in Column
Display images in a DataGrid column using the Template property:
<GridColumn HeaderText="Employee Image" TextAlign="TextAlign.Center" Width="120">
<Template>
@{
var employee = (context as OrderData);
<div class="image">
<img src="@($"scripts/Images/Employees/{employee.EmployeeID}.png")"
alt="@employee.EmployeeID" style="height: 55px; width: 55px; border-radius: 50px;" />
</div>
}
</Template>
</GridColumn>Use cases:
- Employee/product photos
- Status icons
- Custom visual indicators
---
Render Hyperlink in Column
Display hyperlinks in columns using the Template property:
<GridColumn Field="FirstName" HeaderText="First Name" Width="150">
<Template>
@{
var data = (context as EmployeeDetails);
<div>
<a href="https://www.google.com/search?q=@data.FirstName" target="_blank">
@data.FirstName
</a>
</div>
}
</Template>
</GridColumn>Benefits:
- Link to external resources
- Navigate to related pages
- Create interactive content
---
Render Components in Column
Embed Syncfusion or custom components inside columns using the Template property:
<GridColumn HeaderText="Status" Width="150">
<Template>
@{
var data = (context as OrderData);
<SfDropDownList TValue="string" Placeholder="Select Status"
TItem="StatusOption" DataSource="@StatusOptions">
<DropDownListFieldSettings Value="Value"></DropDownListFieldSettings>
</SfDropDownList>
}
</Template>
</GridColumn>Supported components:
- DropDownList
- Sparkline (LineChart, ColumnChart)
- Chip
- ProgressBar
- Custom Blazor components
---
Render DropDownList
Include a DropDownList component in a column:
<GridColumn Field="OrderStatus" HeaderText="Order Status" Width="150">
<Template>
@{
var data = (context as OrderDetails);
<SfDropDownList TValue="string" @bind-Value="@data.OrderStatus"
TItem="StatusOption" DataSource="@EmployeeDetails">
<DropDownListFieldSettings Value="Status"></DropDownListFieldSettings>
</SfDropDownList>
}
</Template>
</GridColumn>Features:
- Inline selection of predefined values
- Two-way binding support
- Custom data source
---
Render Chip
Display data as visually distinct chip/tag elements:
<GridColumn Field="FirstName" HeaderText="First Name" Width="150">
<Template>
@{
var data = (context as EmployeeDetails);
<SfChip ID="chip">
<ChipItems>
<ChipItem Text="@data.FirstName"></ChipItem>
</ChipItems>
</SfChip>
}
</Template>
</GridColumn>Use cases:
- Tagging and labeling
- Visual categorization
- Status display
---
Render ProgressBar
Display progress visualization in columns:
<GridColumn Field="Freight" HeaderText="Freight" Width="150">
<Template>
@{
var data = (context as OrderDetails);
<SfProgressBar Type="ProgressType.Linear" Value="data.Freight"
CornerRadius="CornerType.Square" Height="60"
TrackThickness="24" ProgressThickness="20">
</SfProgressBar>
}
</Template>
</GridColumn>Benefits:
- Visual progress tracking
- Data range visualization
- Professional appearance
Column Validation — Syncfusion Blazor DataGrid
Table of Contents
1. Column Validation 2. Validation Rules 3. Data Annotations 4. Custom Validation 5. Validation Events
---
Column Validation
Column validation ensures that edited or newly added row data meets specific criteria before being saved:
<SfGrid DataSource="@OrderData" Toolbar="@(new List<string>() { "Add", "Edit","Delete", "Update", "Cancel" })">
<GridEditSettings AllowAdding="true" AllowEditing="true" AllowDeleting="true"
Mode="EditMode.Normal"></GridEditSettings>
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" IsPrimaryKey="true"
ValidationRules="@(new ValidationRules{ Required=true, Min=1})"
Width="120"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer Name"
ValidationRules="@(new ValidationRules{ Required=true, MinLength=3})"
Width="120"></GridColumn>
<GridColumn Field="Freight" HeaderText="Freight"
ValidationRules="@(new ValidationRules{ Required=true, Min=1, Max=1000})"
Format="C2" Width="120"></GridColumn>
</GridColumns>
</SfGrid>Benefits:
- Prevent invalid data entry
- Ensure data integrity
- Provide user feedback
- Enforce business rules
---
Validation Rules
Use the ValidationRules property to define validation constraints:
<GridColumn Field="OrderID" HeaderText="Order ID"
ValidationRules="@(new ValidationRules{ Required=true, Min=1, Max=999999})">
</GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer"
ValidationRules="@(new ValidationRules{ Required=true, MinLength=3, MaxLength=50})">
</GridColumn>
<GridColumn Field="Email" HeaderText="Email"
ValidationRules="@(new ValidationRules{ Required=true, RegexPattern="^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"})">
</GridColumn>Available validation rules:
- Required: Field must have a value
- Min: Minimum numeric value
- Max: Maximum numeric value
- MinLength: Minimum string length
- MaxLength: Maximum string length
- RegexPattern: Regular expression pattern matching
---
Data Annotations
Use data annotation attributes to define validation at the model level:
public class OrderDetails
{
[Required]
public int OrderID { get; set; }
[Required]
[StringLength(50, MinimumLength = 3)]
public string CustomerID { get; set; }
[Range(0.01, 10000)]
public double Freight { get; set; }
[EmailAddress]
public string Email { get; set; }
[DataType(DataType.Date)]
public DateTime? OrderDate { get; set; }
}Supported attributes:
[Required]: Field is mandatory[StringLength]: String length constraints[Range]: Numeric range[EmailAddress]: Email format validation[RegularExpression]: Pattern matching[DataType]: Data type specific validation
To use data annotations in Grid:
<SfGrid DataSource="@OrderData" Toolbar="@(new List<string>() { "Add", "Edit", "Update", "Cancel" })">
<GridEditSettings AllowAdding="true" AllowEditing="true" Mode="EditMode.Dialog">
<Validator>
<DataAnnotationsValidator></DataAnnotationsValidator>
</Validator>
</GridEditSettings>
</SfGrid>---
Custom Validation
Implement custom validation logic by creating a validation class:
public class CustomValidationFreight : ValidationAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value != null)
{
double freightValue = Convert.ToDouble(value);
if (freightValue >= 1 && freightValue <= 10000)
{
return ValidationResult.Success;
}
else
{
return new ValidationResult("Freight value should be between 1 and 10,000");
}
}
else
{
return new ValidationResult("Freight value is required");
}
}
}
public class OrderDetails
{
[CustomValidationFreight]
public double Freight { get; set; }
}Using custom validator:
<SfGrid DataSource="@OrderData" Toolbar="@(new List<string>() { "Add", "Edit", "Update", "Cancel" })">
<GridEditSettings AllowAdding="true" AllowEditing="true" Mode="EditMode.Dialog">
<Validator>
<DataAnnotationsValidator></DataAnnotationsValidator>
</Validator>
</GridEditSettings>
</SfGrid>---
Validation Events
Handle validation events for custom logic:
<SfGrid @ref="Grid" DataSource="@OrderData" Toolbar="@(new List<string>() { "Add", "Edit", "Update", "Cancel" })">
<GridEditSettings AllowAdding="true" AllowEditing="true" Mode="EditMode.Dialog">
<Validator>
<DataAnnotationsValidator></DataAnnotationsValidator>
</Validator>
</GridEditSettings>
<GridEvents ActionFailure="OnValidationFailed" ActionComplete="OnActionComplete"
TValue="OrderData"></GridEvents>
</SfGrid>
@code {
private SfGrid<OrderData> Grid;
public void OnValidationFailed(FailedEventArgs args)
{
// Handle validation failure
// args.Error contains error details
}
public void OnActionComplete(ActionEventArgs<OrderData> args)
{
if (args.RequestType == Action.Save)
{
// Data saved successfully after validation
}
}
}Available events:
- ActionFailure: Triggered when validation fails
- ActionComplete: Triggered after successful action
- ActionBegin: Triggered before action starts
Columns — Syncfusion Blazor DataGrid
Table of Contents
1. Column Definition 2. Column Types & Formatting 3. Column Width 4. Controlling Column-Level Grid Actions 5. Render Boolean Values as Checkbox 6. Fixed Columns 7. Responsive Columns (HideAtMedia) 8. Accessing Columns Programmatically 9. Column Headers 10. Stacked Headers 11. Column Visibility 12. Column Reorder 13. Column Resizing 14. Frozen Columns 15. Column Chooser 16. Column Menu 17. Column Spanning 18. Auto-Generated Columns
Related Skills (Detailed Guides)
For in-depth coverage of specific column features, see:
- [Column Headers](column-headers.md) — HeaderText, HeaderTemplate, stacked headers, text alignment, text wrapping
- [Column Template](column-template.md) — Render custom HTML, images, hyperlinks, charts, and Syncfusion components
- [Column Resizing](column-resizing.md) — Enable resizing, set min/max width, prevent resizing, AutoFit columns
- [Column Reorder](column-reorder.md) — Drag-and-drop reordering, programmatic column reordering by index or field
- [Column Spanning](column-spanning.md) — AutoSpan modes, merge cells vertically and horizontally
- [Column Rendering](column-rendering.md) — Manual column definition, auto-generation, primary keys, field binding
- [Column Chooser](column-chooser.md) — Show/hide columns, open dialog programmatically, customize search
- [Column Menu](column-menu.md) — Context menu operations, custom menu items, event handling
- [Column Validation](column-validation.md) — Validation rules, data annotations, custom validators
- [Foreign Key Column](foreignKey-column.md) — Display related data from foreign key sources, local/remote binding, custom editors
- [Frozen Column](frozen-column.md) — Keep columns visible during scrolling, freeze directions, freeze line moving
---
Column Definition
<GridColumn
Field="OrderID"
HeaderText="Order ID"
Width="120"
TextAlign="TextAlign.Right"
Format="C2"
Type="ColumnType.Number"
IsPrimaryKey="true"
AllowSorting="true"
AllowFiltering="true"
AllowEditing="true"
AllowGrouping="true"
AllowSearching="true"
Visible="true"
ClipMode="ClipMode.EllipsisWithTooltip">
</GridColumn>---
Column Types & Formatting
ColumnType | C# Type | Description | Example Format |
|---|---|---|---|
String | string | Text data. Default when Type is not set. | — |
Integer | int | Integer numeric values. | "N0" |
Decimal | decimal | Decimal numeric values. | "C2", "N2" |
Double | double | Double-precision floating-point values. | "C2", "N2" |
Long | long | Long integer values. | "N0" |
Boolean | bool | Boolean values. Renders as text (true/false) by default; use DisplayAsCheckBox="true" to render as checkbox. | — |
CheckBox | — | Renders a checkbox for row selection. Activates multiple-selection mode by default. Do not use for boolean data fields — use Boolean for that. | — |
Date | DateTime (date only) | Date values with formatting support. | "d", "MM/dd/yyyy" |
DateTime | DateTime (with time) | Date and time values. | "dd/MM/yyyy hh:mm a" |
DateOnly | DateOnly | .NET 7+ DateOnly values. | "d" |
TimeOnly | TimeOnly | .NET 7+ TimeOnly values. | "hh:mm" |
None | — | No specific data type specified. | — |
Boolean vs CheckBox:ColumnType.Booleanbinds to a boolean data field and supports editing.ColumnType.CheckBoxis purely for row selection UI and does not bind to data.
<GridColumn Type="ColumnType.CheckBox" Width="50"></GridColumn> <!-- row selection -->
<GridColumn Field="OrderID" Type="ColumnType.Integer" IsPrimaryKey="true" Width="120"></GridColumn>
<GridColumn Field="Freight" Type="ColumnType.Double" Format="C2" TextAlign="TextAlign.Right"></GridColumn>
<GridColumn Field="OrderDate" Type="ColumnType.Date" Format="d" TextAlign="TextAlign.Right"></GridColumn>
<GridColumn Field="IsVerified" Type="ColumnType.Boolean" DisplayAsCheckBox="true"></GridColumn>---
Column Width
The Width property of GridColumn accepts pixels (number), percentages ("25%"), or "auto".
| Width Value | Example | Behavior |
|---|---|---|
| Pixel (number) | Width="120" | Fixed pixel width |
| Percentage | Width="25%" | Responsive, relative to container |
| Auto | Width="auto" | Fit content width |
<GridColumn Field="OrderID" Width="120"></GridColumn> <!-- pixels -->
<GridColumn Field="CustomerID" Width="25%"></GridColumn> <!-- percentage -->
<GridColumn Field="ShipCity" Width="auto"></GridColumn> <!-- auto-fit -->When AllowResizing="true", columns without a specified width default to 200 pixels.---
Controlling Column-Level Grid Actions
Each column can independently allow or deny grid actions using boolean properties on GridColumn:
| Property | Default | Description |
|---|---|---|
AllowSorting | true | Enable/disable sorting for this column |
AllowFiltering | true | Enable/disable filtering for this column |
AllowGrouping | true | Enable/disable grouping for this column |
AllowEditing | true | Enable/disable editing for this column |
AllowResizing | true | Enable/disable resizing for this column |
AllowReordering | true | Enable/disable reordering for this column |
AllowSearching | true | Include/exclude column from global search |
<GridColumn Field="OrderID" AllowEditing="false" AllowGrouping="false" IsPrimaryKey="true"></GridColumn>
<GridColumn Field="CustomerID" AllowSorting="false" AllowFiltering="false"></GridColumn>
<GridColumn Field="Freight" AllowSearching="false" AllowReordering="false"></GridColumn>---
Render Boolean Values as Checkbox
Use DisplayAsCheckBox="true" to render a boolean column as a visual checkbox (read-only display). Pair with Type="ColumnType.Boolean".
<GridColumn Field="IsVerified" HeaderText="Verified"
DisplayAsCheckBox="true"
Type="ColumnType.Boolean"
Width="120">
</GridColumn>For editing boolean values, the column'sEditTypeautomatically usesEditType.BooleanEdit. To render a checkbox in edit mode, setDisplayAsCheckBox="true".
---
Fixed Columns
A fixed column stays at its position regardless of column reordering. Set FixedColumn="true":
<GridColumn Field="OrderID" IsPrimaryKey="true" FixedColumn="true" Width="120"></GridColumn>Fixed columns cannot be moved by drag-and-drop reordering.
---
Responsive Columns (HideAtMedia)
Hide columns on specific screen sizes using the HideAtMedia CSS media query property:
<!-- Hide when viewport is 700px or wider -->
<GridColumn Field="ShipCity" HideAtMedia="(min-width: 700px)" Width="150"></GridColumn>
<!-- Hide on small screens (below 500px) -->
<GridColumn Field="ShipCountry" HideAtMedia="(max-width: 500px)" Width="150"></GridColumn>HideAtMedia accepts any valid CSS media query string. The column is hidden/shown dynamically as the viewport resizes.---
Accessing Columns Programmatically
| Method | Description |
|---|---|
GetColumnsAsync() | Returns all column objects |
GetColumnByFieldAsync(field) | Get column by field name |
GetColumnByUidAsync(uid) | Get column by unique ID |
GetVisibleColumnsAsync() | Get only visible columns |
GetForeignKeyColumnsAsync() | Get all foreign key columns |
GetColumnFieldNamesAsync() | Get array of all field names |
RefreshColumnsAsync() | Re-render columns after dynamic changes |
@code {
SfGrid<Order> Grid;
async Task Example()
{
var allCols = await Grid.GetColumnsAsync();
var col = await Grid.GetColumnByFieldAsync("OrderID");
var visible = await Grid.GetVisibleColumnsAsync();
var fields = await Grid.GetColumnFieldNamesAsync();
// Dynamically add/change columns then refresh:
await Grid.RefreshColumnsAsync();
}
}---
Column Headers
<GridColumn Field="CustomerID" HeaderText="Customer Name">
<HeaderTemplate>
<div>
<span class="e-icons e-user" style="font-size:14px"></span>
Customer
</div>
</HeaderTemplate>
</GridColumn>Text Wrapping
<SfGrid AllowTextWrap="true">
<GridTextWrapSettings WrapMode="WrapMode.Header"></GridTextWrapSettings>
...
</SfGrid>WrapMode: Header, Content, Both.
Custom Attributes on Header
<GridColumn Field="OrderID" HeaderText="Order ID"
CustomAttributes="@(new Dictionary<string,object>{ {"class","custom-header"} })">
</GridColumn>---
Stacked Headers
Group multiple columns under a common header:
<GridColumns>
<GridColumn HeaderText="Order Info">
<Columns>
<GridColumn Field="OrderID" HeaderText="ID" Width="100"></GridColumn>
<GridColumn Field="OrderDate" HeaderText="Date" Width="120"></GridColumn>
</Columns>
</GridColumn>
<GridColumn HeaderText="Ship Info">
<Columns>
<GridColumn Field="ShipCity" Width="120"></GridColumn>
<GridColumn Field="ShipCountry" Width="150"></GridColumn>
</Columns>
</GridColumn>
</GridColumns>---
Column Visibility
Hide/Show via AllowToggle
<GridColumn Field="CustomerID" Visible="true"></GridColumn>
<GridColumn Field="InternalNote" Visible="false"></GridColumn>Programmatic Show/Hide
<SfGrid @ref="Grid" ...>...</SfGrid>
@code {
SfGrid<Order> Grid;
await Grid.HideColumnsAsync(new string[] { "Customer ID" }); // by HeaderText
await Grid.ShowColumnsAsync(new string[] { "Customer ID" });
// Or by field:
await Grid.HideColumnByFieldAsync("CustomerID");
await Grid.ShowColumnByFieldAsync("CustomerID");
// Get all columns:
var cols = await Grid.GetColumnsAsync();
}---
Column Reorder
<SfGrid DataSource="@Orders" AllowReordering="true">
<GridColumns>...</GridColumns>
</SfGrid>Programmatic reorder:
await Grid.ReorderColumnsAsync(new string[] { "ShipCountry", "OrderDate" }, "Freight");
// Moves ShipCountry and OrderDate before Freight columnEvents: ColumnReordering (cancelable), ColumnReordered.
---
Column Resizing
<SfGrid DataSource="@Orders" AllowResizing="true">
<GridColumns>
<GridColumn Field="OrderID" MinWidth="100" MaxWidth="300" Width="150"></GridColumn>
<GridColumn Field="CustomerID" AllowResizing="false" Width="150"></GridColumn>
</GridColumns>
</SfGrid>Events: OnResizeStart, ResizeStopped.
AutoFit Columns
await Grid.AutoFitColumnsAsync(); // All columns
await Grid.AutoFitColumnsAsync(new string[]{"OrderID"}); // Specific columns---
Frozen Columns
Freeze by Count
<SfGrid DataSource="@Orders" FrozenColumns="2" FrozenRows="2">
<GridColumns>
<GridColumn Field="OrderID" Width="120"></GridColumn> <!-- Frozen -->
<GridColumn Field="CustomerID" Width="150"></GridColumn> <!-- Frozen -->
<GridColumn Field="Freight" Width="120"></GridColumn>
</GridColumns>
</SfGrid>Freeze Individual Columns
<GridColumn Field="OrderID" IsFrozen="true" Freeze="FreezeDirection.Left" Width="120"></GridColumn>
<GridColumn Field="ShipCountry" IsFrozen="true" Freeze="FreezeDirection.Right" Width="150"></GridColumn>FreezeDirection: Left, Right, Fixed.
---
Column Chooser
Allow users to show/hide columns via a dialog:
<SfGrid DataSource="@Orders" ShowColumnChooser="true"
Toolbar="@(new List<string>() { "ColumnChooser" })">
<GridColumns>
<GridColumn Field="OrderID" ShowInColumnChooser="false"></GridColumn> <!-- Always visible -->
<GridColumn Field="CustomerID"></GridColumn>
<GridColumn Field="ShipCountry"></GridColumn>
</GridColumns>
</SfGrid>Programmatic open:
await Grid.OpenColumnChooserAsync(100, 50); // x, y positionCustom column chooser template:
<SfGrid ShowColumnChooser="true">
<GridColumnChooserSettings Operator="SearchOperatorType.Contains"></GridColumnChooserSettings>
...
</SfGrid>---
Column Menu
Right-click header for column operations:
<SfGrid DataSource="@Orders" ShowColumnMenu="true">
<GridColumnMenuSettings ShowColumnChooser="true"></GridColumnMenuSettings>
<GridColumns>
<GridColumn Field="OrderID" ColumnMenuItems="@(new List<string>{"AutoFit"})"></GridColumn>
</GridColumns>
</SfGrid>Default items: AutoFit, AutoFitAll, SortAscending, SortDescending, Group, Ungroup, ColumnChooser, Filter.
Custom items:
<SfGrid ShowColumnMenu="true">
<GridColumnMenuItems>
<GridColumnMenuItem Text="Custom Action" Id="customItem"></GridColumnMenuItem>
</GridColumnMenuItems>
<GridEvents TValue="Order" ColumnMenuItemClicked="OnMenuItemClicked"></GridEvents>
...
</SfGrid>
@code {
void OnMenuItemClicked(ColumnMenuClickEventArgs args)
{
if (args.Item.Id == "customItem") { /* custom logic */ }
}
}Events: OnColumnMenuOpen, ColumnMenuItemClicked.
---
Column Spanning
Merge cells across columns:
<SfGrid DataSource="@Orders">
<GridEvents TValue="Order" QueryCellInfo="QueryCellInfoHandler"></GridEvents>
<GridColumns>
<GridColumn Field="OrderID" Width="120"></GridColumn>
<GridColumn Field="CustomerID" Width="150"></GridColumn>
<GridColumn Field="ShipCity" Width="120"></GridColumn>
</GridColumns>
</SfGrid>
@code {
void QueryCellInfoHandler(QueryCellInfoEventArgs<Order> args)
{
// Span CustomerID column over next 2 columns for row 0
if (args.Data.OrderID == 10248 && args.Column.Field == "CustomerID")
{
args.ColSpan = 2;
}
}
}---
Auto-Generated Columns
When no <GridColumns> is defined, columns are auto-generated from the model:
<SfGrid DataSource="@Orders">
<!-- No GridColumns block — columns auto-generated from Order properties -->
</SfGrid>Control auto-generation with AutoGenerateColumns="true" (default when no GridColumns defined).
For ExpandoObject
<SfGrid DataSource="@DynamicOrders">
<GridColumns>
<GridColumn Field="OrderID" HeaderText="Order ID" IsPrimaryKey="true"></GridColumn>
<GridColumn Field="CustomerID" HeaderText="Customer"></GridColumn>
</GridColumns>
</SfGrid>Context Menu — Syncfusion Blazor DataGrid
Table of Contents
- Enable Context Menu
- Default Context Menu Items
- Custom Context Menu Items
- Mixed Built-in + Custom Items
- Sub-menu Items
- ContextMenuItemModel Properties
- Context Menu Events
- Disable Context Menu for Specific Columns
- Enable or Disable Context Menu Items Dynamically
- Show or Hide Context Menu Items Dynamically
- Access Specific Row Details on Context Menu Click
Enable Context Menu
Set ContextMenuItems on SfGrid with built-in string keys. Requires AllowSorting, AllowGrouping, AllowPaging, export flags, and GridEditSettings for the relevant items to appear.
<SfGrid DataSource="@Orders" AllowSorting="true" AllowPaging="true" AllowGrouping="true"
AllowExcelExport="true" AllowPdfExport="true" ContextMenuItems="@ContextMenuItems">
<GridEditSettings AllowEditing="true" AllowDeleting="true"></GridEditSettings>
...
</SfGrid>
@code {
List<object> ContextMenuItems = new()
{
"AutoFit", "AutoFitAll", "SortAscending", "SortDescending",
"Copy", "Edit", "Delete", "Save", "Cancel",
"PdfExport", "ExcelExport", "CsvExport",
"FirstPage", "PrevPage", "LastPage", "NextPage", "Group", "Ungroup"
};
}Default Context Menu Items
Header area:
| Item | Description |
|---|---|
"AutoFit" | Auto-fit current column width |
"AutoFitAll" | Auto-fit all column widths |
"Group" | Group by current column |
"Ungroup" | Remove group on current column |
"SortAscending" | Sort column ascending |
"SortDescending" | Sort column descending |
Content area:
| Item | Description |
|---|---|
"Edit" | Edit selected row |
"Delete" | Delete selected row |
"Save" | Save current edit |
"Cancel" | Cancel current edit |
"Copy" | Copy selected rows |
"PdfExport" | Export to PDF |
"ExcelExport" | Export to Excel |
"CsvExport" | Export to CSV |
Pager area:
| Item | Description |
|---|---|
"FirstPage" | Go to first page |
"PrevPage" | Go to previous page |
"LastPage" | Go to last page |
"NextPage" | Go to next page |
Custom Context Menu Items
<SfGrid @ref="Grid" DataSource="@Employees" AllowPaging="true"
ContextMenuItems="@CustomMenuItems">
<GridEvents ContextMenuItemClicked="OnContextMenuClick" TValue="Employee"></GridEvents>
<GridColumns>...</GridColumns>
</SfGrid>
@code {
SfGrid<Employee> Grid;
List<ContextMenuItemModel> CustomMenuItems = new()
{
new ContextMenuItemModel
{
Text = "Copy with headers",
Target = ".e-content",
Id = "copywithheader"
}
};
async Task OnContextMenuClick(ContextMenuClickEventArgs<Employee> args)
{
if (args.Item.Id == "copywithheader")
{
await Grid.CopyAsync(true); // copy with headers
}
}
}Mixed Built-in + Custom Items
<SfGrid DataSource="@Orders"
ContextMenuItems="@(new List<object>
{
"Copy",
new ContextMenuItemModel { Text = "Copy with headers", Target = ".e-content", Id = "copywithheader" }
})">
<GridEvents ContextMenuItemClicked="OnContextMenuClick" TValue="Order"></GridEvents>
...
</SfGrid>Sub-menu Items
Sub-items must use List<Syncfusion.Blazor.Navigations.MenuItem> (not List<ContextMenuItemModel>) for the Items property.
@code {
List<ContextMenuItemModel> ContextMenuItems = new()
{
new ContextMenuItemModel
{
Text = "Clipboard", Target = ".e-content", Id = "clipboard",
Items = new List<Syncfusion.Blazor.Navigations.MenuItem>
{
new Syncfusion.Blazor.Navigations.MenuItem { Text = "Copy", Id = "copy" },
new Syncfusion.Blazor.Navigations.MenuItem { Text = "Copy With Header", Id = "copywithheader" }
}
}
};
async Task OnContextMenuClick(ContextMenuClickEventArgs<OrderData> args)
{
if (args.Item.Id == "copy") await Grid.CopyAsync(false);
else if (args.Item.Id == "copywithheader") await Grid.CopyAsync(true);
}
}ContextMenuItemModel Properties
| Property | Type | Description |
|---|---|---|
Text | string | Display text of the menu item |
Id | string | Unique identifier for handling clicks |
Target | string | CSS selector for where the item appears (.e-headercell, .e-content, .e-pager) |
IconCss | string | CSS icon class |
Items | List<Syncfusion.Blazor.Navigations.MenuItem> | Sub-menu items (use MenuItem, not ContextMenuItemModel) |
Disabled | bool | Disables the menu item so it cannot be clicked |
Hidden | bool | Hides the menu item from view |
Context Menu Events
| Event | Args Type | Description |
|---|---|---|
ContextMenuItemClicked | ContextMenuClickEventArgs<T> | Fires when a context menu item is clicked; use args.Item.Id and args.RowInfo.RowData |
ContextMenuOpen | ContextMenuOpenEventArgs<T> | Fires before context menu opens; use args.Cancel, args.Column.Field, args.ContextMenu.Items |
ContextMenuOpenEventArgs key members
| Member | Description |
|---|---|
args.Cancel | Set to true to prevent the context menu from opening |
args.Column.Field | The field name of the column where right-click occurred |
args.ContextMenu.Items | Collection of menu items; set item.Disabled or item.Hidden per item |
ContextMenuClickEventArgs key members
| Member | Description |
|---|---|
args.Item.Id | The Id of the clicked menu item |
args.RowInfo.RowData | The full data object of the row that was right-clicked |
Disable Context Menu for Specific Columns
Use the ContextMenuOpen event and set args.Cancel = true to prevent the context menu from opening on a particular column.
@code {
void OnContextMenuOpen(ContextMenuOpenEventArgs<OrderData> args)
{
if (args.Column.Field == "Freight")
args.Cancel = true; // suppress context menu for this column
}
}Enable or Disable Context Menu Items Dynamically
Use args.ContextMenu.Items inside ContextMenuOpen to set item.Disabled = true/false per column or row condition.
@code {
// Disable "Copy" only when right-clicking the ShipCity column
void OnContextMenuOpen(ContextMenuOpenEventArgs<OrderData> args)
{
foreach (var item in args.ContextMenu.Items)
{
item.Disabled = item.Text == "Copy" && args.Column.Field == nameof(OrderData.ShipCity);
}
}
}Show or Hide Context Menu Items Dynamically
Use item.Hidden = true/false inside ContextMenuOpen to show or hide individual items.
Note: The display text for the built-in"Edit"item is"Edit Record"at runtime. Useitem.Text == "Edit Record"when matching by text insideContextMenuOpen.
@code {
// Hide "Edit Record" item when right-clicking the CustomerID column
void OnContextMenuOpen(ContextMenuOpenEventArgs<OrderData> args)
{
foreach (var item in args.ContextMenu.Items)
{
if (item.Text == "Edit Record" && args.Column.Field == nameof(OrderData.CustomerID))
item.Hidden = true;
}
}
}Access Specific Row Details on Context Menu Click
Use args.RowInfo.RowData in the ContextMenuItemClicked event to retrieve the full data object of the right-clicked row.
@code {
OrderData selectedRow;
void OnContextMenuClick(ContextMenuClickEventArgs<OrderData> args)
{
if (args.Item.Id == "fetchdata")
selectedRow = args.RowInfo.RowData; // full row object
}
}
Editing Patterns — Syncfusion Blazor DataGrid
Advanced editing behaviors, row-level controls, and UI patterns.
Table of Contents
- Cancel Edit Based on Condition
- Disable Editing for a Specific Row
- Provide New/Edited Item via Events
- Default Column Values
- New Row Position
- Always Show Add-New-Row Form
- Delete Multiple Rows
- Single-Click Editing
- Saving a New Row at a Specific Index
- Inline Template Editing
- Limitations
Cancel Edit Based on Condition
Set args.Cancel = true inside edit/add/delete events to conditionally block CRUD:
<GridEvents TValue="Order"
RowEditing="OnRowEditing"
RowCreating="OnRowCreating"
RowDeleting="OnRowDeleting">
</GridEvents>
@code {
void OnRowEditing(RowEditingEventArgs<Order> args)
{
if (args.Data.Role == "Admin") args.Cancel = true; // block edit
}
void OnRowCreating(RowCreatingEventArgs<Order> args)
{
if (!IsAddAllowed) args.Cancel = true; // block add
}
void OnRowDeleting(RowDeletingEventArgs<Order> args)
{
if (args.Datas[0].Role == "Admin") args.Cancel = true; // block delete
}
}RowDeletingusesargs.Datas(array), notargs.Data.
Batch mode equivalents:
| Batch Event | Cancelable | Purpose |
|---|---|---|
OnCellEdit | ✅ | Block editing a specific cell |
OnBatchAdd | ✅ | Block adding a new row |
OnBatchDelete | ✅ | Block deleting a row |
Disable Editing for a Specific Row
<GridEvents TValue="Order" RowEditing="OnRowEditing"></GridEvents>
@code {
void OnRowEditing(RowEditingEventArgs<Order> args)
{
if (args.Data.ShipCountry == "France")
args.Cancel = true;
}
}Provide New/Edited Item via Events
Use when the model has no parameterless constructor, or when custom initialization is needed. Grid uses Activator.CreateInstance<TValue>() by default — if this fails, supply instances manually:
<GridEvents TValue="Order"
RowCreating="OnRowCreating"
OnBeginEdit="OnBeginEdit">
</GridEvents>
@code {
void OnRowCreating(RowCreatingEventArgs<Order> args)
{
// Set default values on the new row object
args.Data.CustomerID = "HANAR";
args.Data.Freight = 5.0;
args.Data.ShipCountry = "Brazil";
}
void OnBeginEdit(BeginEditArgs<Order> args)
{
// Provide a manual deep-clone for the edited row
args.RowData = new Order(args.RowData.OrderID, args.RowData.CustomerID,
args.RowData.Freight, args.RowData.ShipCountry);
}
}Grid.AddRecordAsync(newRecord, index) can also inject a pre-built record at a specific index.Default Column Values
Pre-fill specific columns when a new row is added using GridColumn.DefaultValue:
<GridColumn Field="CustomerID" DefaultValue="@("HANAR")" Width="120"></GridColumn>
<GridColumn Field="Freight" EditType="EditType.NumericEdit" DefaultValue="@(1.0)" Width="120"></GridColumn>
<GridColumn Field="ShipCountry" EditType="EditType.DropDownEdit" DefaultValue="@("France")" Width="150"></GridColumn>DefaultValueis typed asobject. Pass the value as the correct runtime type.
New Row Position
<GridEditSettings AllowAdding="true" Mode="EditMode.Normal"
NewRowPosition="NewRowPosition.Bottom">
</GridEditSettings>| Value | Description |
|---|---|
NewRowPosition.Top | Insert new row at top (default) |
NewRowPosition.Bottom | Insert new row at bottom |
Supported in Normal and Batch modes only.
Always Show Add-New-Row Form
Keeps a persistent blank form visible for continuous data entry:
<GridEditSettings AllowAdding="true" Mode="EditMode.Normal"
ShowAddNewRow="true"
NewRowPosition="NewRowPosition.Top">
</GridEditSettings>Press Enter or click Update in the toolbar to commit the new record.
Limitations:
- Normal mode only — not supported in Dialog or Batch
- With Virtual/Infinite Scrolling, new row always appears at top regardless of
NewRowPosition - Not compatible with Column Virtualization
Delete Multiple Rows
<SfGrid DataSource="@Orders" Toolbar="@(new List<string>{ "Delete" })">
<GridEditSettings AllowDeleting="true"></GridEditSettings>
<GridSelectionSettings Type="SelectionType.Multiple"></GridSelectionSettings>
...
</SfGrid>Select rows (checkbox or click), then click Delete toolbar item — or call programmatically:
await Grid.DeleteRecordAsync(); // deletes all currently selected rowsEnableShowDeleteConfirmDialog="true"onGridEditSettingsto prevent accidental deletions.
Single-Click Editing
Trigger edit mode on a single row click using OnRecordClick:
<SfGrid @ref="Grid" DataSource="@Orders">
<GridEditSettings AllowEditing="true" Mode="EditMode.Normal"></GridEditSettings>
<GridEvents TValue="Order" OnRecordClick="RecordClickHandler"></GridEvents>
...
</SfGrid>
@code {
SfGrid<Order> Grid;
int? CurrentRowIndex;
async Task RecordClickHandler(RecordClickEventArgs<Order> args)
{
if (Grid.IsEdit && CurrentRowIndex != args.RowIndex)
await Grid.EndEditAsync(); // save/close previous row
CurrentRowIndex = args.RowIndex;
await Grid.SelectRowAsync(args.RowIndex);
await Grid.StartEditAsync();
}
}Saving a New Row at a Specific Index
Use OnActionBegin to override where a newly added row is saved in the datasource:
<GridEvents TValue="Order" OnActionBegin="OnActionBegin"></GridEvents>
@code {
void OnActionBegin(ActionEventArgs<Order> args)
{
if (args.RequestType == Action.Save && args.Action == "Add")
{
// Save at end of current page
args.Index = (Grid.PageSettings.CurrentPage * Grid.PageSettings.PageSize) - 1;
}
}
}Inline Template Editing
Replace the entire edit row with a fully custom layout using GridEditSettings.Template:
<GridEditSettings AllowEditing="true" AllowAdding="true" Mode="EditMode.Normal">
<Template>
@{
var order = context as Order;
}
<table>
<tr>
<td><SfNumericTextBox @bind-Value="order.OrderID" Enabled="false"></SfNumericTextBox></td>
<td><SfTextBox @bind-Value="order.CustomerID"></SfTextBox></td>
<td><SfNumericTextBox @bind-Value="order.Freight"></SfNumericTextBox></td>
<td><SfDropDownList @bind-Value="order.ShipCountry" DataSource="@Countries">
<DropDownListFieldSettings Text="Name" Value="Name"></DropDownListFieldSettings>
</SfDropDownList>
</td>
</tr>
</table>
</Template>
</GridEditSettings>All custom editors must use `@bind-Value` for two-way data binding.
Limitations
| Limitation | Detail |
|---|---|
| Command column — no Add | Command buttons render only after a record exists; Add is not supported via command column |
| `ShowAddNewRow` | Normal mode only; always at top with Virtual/Infinite Scrolling; incompatible with Column Virtualization |
| `NewRowPosition` | Supported in Normal and Batch modes only |
| `SetCellValueAsync` | Updates Grid UI only — does not persist to the underlying datasource |
| `UpdateCellAsync` | Batch mode only — queues the cell change until ApplyBatchChangesAsync is called |
| `AddRecordAsync` / `StartEditAsync` | Normal and Dialog modes only; not applicable in Batch mode |
| Parameterless constructor | Grid uses Activator.CreateInstance<TValue>() — model must have a parameterless constructor, or supply instances via RowCreating/OnBeginEdit |
| `IsIdentity` columns | Treated as read-only during both add and edit operations |
| Validation timing | Messages re-trigger only on form submit or field blur (Blazor EditForm behavior) |
| Complex type validation | Requires [ValidateComplexType] + Microsoft.AspNetCore.Components.DataAnnotations.Validation NuGet |
| Dialog max height | Capped at ~658px on 1920×1080 screens |
| `AllowEditing=false` on column | Disables editing only; column still appears in add form unless AllowAdding=false is also set |
Getting Started — App Type Variants
Blazor Server App
Program.cs
using Syncfusion.Blazor;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorComponents().AddInteractiveServerComponents();
builder.Services.AddSyncfusionBlazor();
var app = builder.Build();
app.MapRazorComponents<App>().AddInteractiveServerRenderMode();
app.Run();App.razor — Add stylesheets in <head>
<head>
...
<link href="_content/Syncfusion.Blazor.Themes/bootstrap5.css" rel="stylesheet" />
</head>
<body>
...
<script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js"></script>
</body>Page Component
No special render mode directive needed when interactivity is set globally. If per-page interactivity:
@rendermode InteractiveServer---
Blazor Web App (.NET 8+)
Supports multiple render modes. Setup requires both server and client projects.
Server Program.cs
using Syncfusion.Blazor;
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents()
.AddInteractiveWebAssemblyComponents();
builder.Services.AddSyncfusionBlazor();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode()
.AddInteractiveWebAssemblyRenderMode()
.AddAdditionalAssemblies(typeof(Client._Imports).Assembly);Client Program.cs
using Syncfusion.Blazor;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Services.AddSyncfusionBlazor();
await builder.Build().RunAsync();App.razor (Server Project)
<head>
<link href="_content/Syncfusion.Blazor.Themes/bootstrap5.css" rel="stylesheet" />
</head>
<body>
<Routes />
<script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js"></script>
</body>Render Mode on Page
@rendermode InteractiveAuto @* Server first, then WASM *@
@rendermode InteractiveWebAssembly @* Pure WASM *@
@rendermode InteractiveServer @* Server-side *@---
Blazor MAUI App
MauiProgram.cs
using Syncfusion.Blazor;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts => { ... });
builder.Services.AddMauiBlazorWebView();
builder.Services.AddSyncfusionBlazor();
return builder.Build();
}
}wwwroot/index.html
<head>
<link href="_content/Syncfusion.Blazor.Themes/bootstrap5.css" rel="stylesheet" />
</head>
<body>
<app>...</app>
<script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js"></script>
</body>---
License Key Registration
For production apps, register license in Program.cs before builder.Build():
Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("YOUR-LICENSE-KEY");Obtain a free community key or trial from https://www.syncfusion.com/sales/products.
---
_Imports.razor (All Project Types)
@using Syncfusion.Blazor
@using Syncfusion.Blazor.Grids