What is a Data Grid?
A Data Grid is a UI component that displays and manipulates tabular data. Unlike a standard HTML table, which is static and requires manual work for every interaction, a Data Grid provides sorting, filtering, paging, and inline editing out of the box.
Think of the difference between a printed spreadsheet and a live Excel file. One is read-only; the other lets you search, sort, filter, and edit in place. A Data Grid brings that same interactive experience to the browser.
Why DevExpress MVC Data Grid?
The DevExpress MVC GridView is an enterprise-grade component built for real business applications. It handles millions of rows through server-mode binding, supports master-detail relationships for parent-child data, and provides batch editing so users can modify multiple rows and save everything in a single request. These are not theoretical features; they are the building blocks of systems like invoice management, warehouse tracking, and financial reporting.
In this guide, we will build one such system step by step. Each section adds a new capability, and each includes a live, interactive grid so you can see the feature working in your browser right now.
The Scenario: Invoice Management System
We are building an Invoice Management System. It handles three types of documents: Sales Invoices, Credit Notes, and Rental Invoices. Each invoice belongs to a company, has a date and total amount, and can contain one or more line items (the individual products or services being billed). By the end of this guide, the grid will support filtering, master-detail drill-down, inline editing, and data export.
Step 1: The Humble HTML Table
Every web developer starts here. A plain HTML <table> can display data, but it does nothing beyond that. There is no sorting, no filtering, no paging. If you have 10,000 invoices, they all render at once. If a user wants to find a specific company, they have to scroll manually or rely on the browser's Ctrl+F. Adding any of these features means writing custom JavaScript, managing state, and handling edge cases around pagination and URL parameters.
Below is the same invoice data rendered in a plain table. It looks fine for four rows, but imagine this with hundreds.
| Invoice # | Type | Company | Date | Total | Status |
|---|---|---|---|---|---|
| INV-001 | Sales Invoice | Tech Solutions Ltd | 5/29/2026 | $1,500.00 | Paid |
| CRN-001 | Credit Note | Global Trade Co | 5/31/2026 | ($250.00) | Processed |
| RNL-001 | Rental Invoice | Urban Living | 6/2/2026 | $3,200.00 | Pending |
| INV-002 | Sales Invoice | Pioneer Systems | 6/3/2026 | $450.00 | Paid |
This table is a dead end. To add sorting alone, you would need JavaScript event handlers on every column header, a comparison function for each data type (string, date, currency), and logic to re-render the rows. Paging would require tracking the current page index, slicing the data, and rendering navigation controls. The DevExpress GridView handles all of this with a few lines of configuration.
Step 2: Transitioning to DevExpress GridView
The first step is replacing that HTML table with a DevExpress GridView. At this stage we are not adding any advanced features. We simply define the columns, point the grid at our data, and let the component handle rendering.
The grid needs three things: a Model class that describes the shape of the data, a Controller action that fetches the data and returns a partial view, and a Razor partial view that configures the grid columns and binds the model.
public class Invoice
{
public int ID { get; set; }
public string InvoiceNumber { get; set; }
public string Type { get; set; }
public string CompanyName { get; set; }
public string Address { get; set; }
public DateTime Date { get; set; }
public decimal TotalAmount { get; set; }
public string Status { get; set; }
}
@model List<Invoice>
@Html.DevExpress().GridView(settings => {
settings.Name = "gvInvoicesBasic";
settings.KeyFieldName = "ID";
settings.CallbackRouteValues = new {
Controller = "DevExpress",
Action = "InvoicesBasicGridPartial"
};
settings.Width = Unit.Percentage(100);
settings.Columns.Add("InvoiceNumber");
settings.Columns.Add("Type");
settings.Columns.Add("CompanyName");
settings.Columns.Add("Date").PropertiesEdit.DisplayFormatString = "d";
settings.Columns.Add("TotalAmount").PropertiesEdit.DisplayFormatString = "c";
settings.Columns.Add("Status");
}).Bind(Model).GetHtml()
[ValidateInput(false)]
public ActionResult InvoicesBasicGridPartial()
{
return PartialView("_InvoicesBasicGridPartial", GetInvoices());
}
private List<Invoice> GetInvoices()
{
if (Session["Invoices"] == null)
{
Session["Invoices"] = new List<Invoice>
{
new Invoice {
ID = 1,
InvoiceNumber = "INV-001",
Type = "Sales Invoice",
CompanyName = "Tech Solutions Ltd",
Date = DateTime.Today.AddDays(-5),
TotalAmount = 1500.00m,
Status = "Paid"
},
// ... more invoices
};
}
return (List<Invoice>)Session["Invoices"];
}
The Live Result
|
With roughly 15 lines of Razor configuration, we have a professional grid with automatic column rendering, currency and date formatting, and click-to-sort. The Controller action is a simple pass-through that fetches the data from the session and returns a partial view. This separation of concerns (Model, View, Controller) is the foundation of every DevExpress MVC grid.
Step 3: Paging, Filtering, and Search
A grid that only sorts is not enough for production use. When you have hundreds or thousands of invoices, users need to narrow down what they see. DevExpress provides three tools for this: a pager that breaks data into pages, a filter row that lets users type a value at the top of any column, and a search panel that searches across all columns at once.
These features are enabled purely through configuration. No custom JavaScript, no extra controller logic. The grid handles the filtering and paging on the server automatically via AJAX callbacks.
Three new settings are added to the grid configuration:
1. PageSize controls how many rows appear per page
2. ShowFilterRow adds a text input above each column
3. SettingsSearchPanel.Visible adds a global search box
The model and controller remain identical to Step 2.
No server-side filtering code is needed; DevExpress
handles it internally through its callback mechanism.
@Html.DevExpress().GridView(settings => {
settings.Name = "gvInvoicesFilter";
settings.KeyFieldName = "ID";
settings.CallbackRouteValues = new {
Controller = "DevExpress",
Action = "InvoicesFilterGridPartial"
};
settings.Width = Unit.Percentage(100);
settings.Columns.Add("InvoiceNumber");
settings.Columns.Add("Type");
settings.Columns.Add("CompanyName");
settings.Columns.Add("Date").PropertiesEdit.DisplayFormatString = "d";
settings.Columns.Add("TotalAmount").PropertiesEdit.DisplayFormatString = "c";
settings.Columns.Add("Status");
// Paging
settings.SettingsPager.PageSize = 10;
// Filtering
settings.Settings.ShowFilterRow = true;
settings.SettingsSearchPanel.Visible = true;
// Row focus
settings.SettingsBehavior.AllowFocusedRow = true;
}).Bind(Model).GetHtml()
[ValidateInput(false)]
public ActionResult InvoicesFilterGridPartial()
{
return PartialView("_InvoicesFilterGridPartial", GetInvoices());
}
// The controller action is identical in structure to Step 2.
// DevExpress handles filtering and paging internally.
// The grid sends AJAX callbacks to this action, passing
// filter and page parameters automatically.
The Live Result
|
The filter row supports different matching modes depending on the column type. Text columns default to "Contains" matching, date columns provide a date picker, and numeric columns support range comparisons. All of this is handled by the DevExpress framework without any additional code on your part.
Step 4: Master-Detail Relationships
Most real-world data is relational. An invoice (the master record) contains one or more line items (the detail records). Rather than navigating to a separate page for each invoice's items, a master-detail grid lets users expand a row in place and see its child records directly.
DevExpress supports this through a detail row template. When a user clicks the expand icon next to a row, the grid calls a separate controller action to fetch the child data and renders it inside a nested grid. The child grid is a fully independent component with its own columns, formatting, and summary footer.
public class InvoiceLine
{
public int ID { get; set; }
public int InvoiceID { get; set; }
public string Description { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
public decimal LineTotal => Quantity * UnitPrice;
}
// The LineTotal property is computed, not stored.
// DevExpress reads it like any other property and
// can include it in summaries and exports.
// Added to the master grid settings:
settings.SettingsDetail.ShowDetailRow = true;
settings.SetDetailRowTemplateContent(c => {
Html.RenderAction("InvoiceLinesGridPartial", new {
invoiceId = DataBinder.Eval(c.DataItem, "ID")
});
});
// When the user expands a row, DevExpress calls
// InvoiceLinesGridPartial with the invoice's ID.
// The detail grid renders inside the expanded row.
[ValidateInput(false)]
public ActionResult InvoicesMasterDetailGridPartial()
{
return PartialView(
"_InvoicesMasterDetailGridPartial",
GetInvoices()
);
}
[ValidateInput(false)]
public ActionResult InvoiceLinesGridPartial(int invoiceId)
{
ViewBag.InvoiceID = invoiceId;
return PartialView(
"_InvoiceLinesGridPartial",
GetInvoiceLines(invoiceId)
);
}
private List<InvoiceLine> GetInvoiceLines(int invoiceId)
{
var lines = new List<InvoiceLine>();
if (invoiceId == 1)
{
lines.Add(new InvoiceLine {
ID = 1, InvoiceID = 1,
Description = "Web Development Service",
Quantity = 1, UnitPrice = 1000.00m
});
lines.Add(new InvoiceLine {
ID = 2, InvoiceID = 1,
Description = "UI/UX Design",
Quantity = 5, UnitPrice = 100.00m
});
}
return lines;
}
The Live Result
|
Each nested grid is a complete DevExpress GridView with its own callback route. This means you could add paging, filtering, or editing to the detail grid independently. The parent and child grids communicate only through the invoice ID passed in the expand callback.
Step 5: Batch Editing
Traditional web forms force users to edit one record at a time: click an edit button, modify values, save, go back, repeat. For data-heavy workflows like invoice management, this is painfully slow. Batch editing turns the grid into something closer to a spreadsheet. Users click a cell to edit it, tab to the next cell, make all their changes, and then save everything in a single request.
DevExpress tracks all modifications client-side. Changed cells are highlighted in green. Deleted rows are marked in red. New rows appear at the top. When the user clicks Save, the grid sends all inserts, updates, and deletes to the server in one POST request, packaged in a MVCxGridViewBatchUpdateValues object.
Batch editing requires three additions:
1. View: Set the editing mode to Batch and configure
permissions (AllowEdit, AllowInsert, AllowDelete).
Add a CommandColumn for the New and Delete buttons.
Set ShowStatusBar to display the Save/Cancel bar.
2. Controller: Add a new action that accepts
MVCxGridViewBatchUpdateValues. This object contains
three collections: Insert, Update, and DeleteKeys.
3. Route: Set BatchUpdateRouteValues on the grid
to point to the new controller action.
// Added to the grid settings:
settings.SettingsEditing.Mode = GridViewEditingMode.Batch;
settings.SettingsEditing.BatchEditSettings.EditMode
= GridViewBatchEditMode.Cell;
settings.SettingsEditing.BatchEditSettings.StartEditAction
= GridViewBatchStartEditAction.Click;
settings.SettingsEditing.BatchUpdateRouteValues = new {
Controller = "DevExpress",
Action = "InvoicesBatchUpdate"
};
settings.SettingsDataSecurity.AllowEdit = true;
settings.SettingsDataSecurity.AllowInsert = true;
settings.SettingsDataSecurity.AllowDelete = true;
settings.Settings.ShowStatusBar = GridViewStatusBarMode.Visible;
settings.CommandColumn.Visible = true;
settings.CommandColumn.ShowNewButtonInHeader = true;
settings.CommandColumn.ShowDeleteButton = true;
[HttpPost, ValidateInput(false)]
public ActionResult InvoicesBatchUpdate(
MVCxGridViewBatchUpdateValues<Invoice, int> updateValues)
{
var model = GetInvoices();
// Process new rows
foreach (var item in updateValues.Insert)
{
if (updateValues.IsValid(item))
{
item.ID = model.Max(x => x.ID) + 1;
model.Add(item);
}
}
// Process modified rows
foreach (var item in updateValues.Update)
{
if (updateValues.IsValid(item))
{
var target = model.FirstOrDefault(x => x.ID == item.ID);
if (target != null)
{
target.InvoiceNumber = item.InvoiceNumber;
target.CompanyName = item.CompanyName;
target.Status = item.Status;
}
}
}
// Process deleted rows
foreach (var id in updateValues.DeleteKeys)
{
var target = model.FirstOrDefault(x => x.ID == id);
if (target != null) model.Remove(target);
}
return PartialView("_InvoicesGridPartial", model);
}
The Live Result
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Batch editing is particularly valuable in scenarios where users need to update many records quickly, such as adjusting invoice statuses at month-end or correcting bulk data imports. The single round-trip to the server means better performance and a smoother user experience compared to row-by-row editing.
Step 6: Summaries, Aggregates, and Final Polish
A production grid needs more than just data display and editing. Users expect footer totals, row counts, and the ability to export what they see to a spreadsheet or PDF. DevExpress provides summary aggregates (sum, count, average, min, max) that render in the grid footer, and a server-side export API that produces formatted Excel, PDF, CSV, and RTF files.
The grid below combines every feature from the previous steps: sorting, filtering, search, master-detail, batch editing, summary totals, and row counts. This is the complete invoice management grid.
Two additions for this final step:
1. Footer summaries: ShowFooter = true, then add
TotalSummary items for Sum and Count aggregates.
These update automatically when data changes.
2. Export: DevExpress provides GridViewExtension export
methods (ExportToXlsx, ExportToPdf, ExportToCsv).
Each takes the grid settings and data, and returns
an ActionResult that downloads the file.
Supported formats: XLS, XLSX, PDF, RTF, CSV, DOCX
// Footer summaries
settings.Settings.ShowFooter = true;
settings.TotalSummary.Add(
DevExpress.Data.SummaryItemType.Sum,
"TotalAmount"
).DisplayFormat = "Total: {0:c}";
settings.TotalSummary.Add(
DevExpress.Data.SummaryItemType.Count,
"InvoiceNumber"
).DisplayFormat = "{0} invoices";
// Export is handled server-side:
// GridViewExtension.ExportToXlsx(settings, data);
// GridViewExtension.ExportToPdf(settings, data);
// GridViewExtension.ExportToCsv(settings, data);
// Export action example:
public ActionResult ExportInvoicesToPdf()
{
var settings = new GridViewSettings();
settings.Name = "gvInvoicesExport";
settings.Columns.Add("InvoiceNumber");
settings.Columns.Add("Type");
settings.Columns.Add("CompanyName");
settings.Columns.Add("Date")
.PropertiesEdit.DisplayFormatString = "d";
settings.Columns.Add("TotalAmount")
.PropertiesEdit.DisplayFormatString = "c";
settings.Columns.Add("Status");
return GridViewExtension.ExportToPdf(
settings,
GetInvoices()
);
}
// Each format has its own method:
// ExportToXlsx, ExportToPdf, ExportToCsv, etc.
// The exported file respects column formatting,
// visibility, and sort order.
The Live Result
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Export to Excel, PDF, or CSV
Click the buttons below to download the invoice data in different formats. The exported file respects column formatting, visibility, and sort order.
From summaries and aggregates in the footer to responsive layouts that adapt to smaller screens, the DevExpress GridView is designed to grow with your application. Every feature we have covered (sorting, filtering, master-detail, batch editing, summaries, export) works together without conflict, because the component was designed as a cohesive system rather than a collection of add-ons.
Step 7: Inline Row Editing (Edit/Update/Cancel)
Inline editing is the classic approach where each row has Edit and Delete buttons. When a user clicks Edit, the row transforms into an editable form with input controls. After making changes, the user clicks Update to save or Cancel to discard. This is ideal when you want to control changes one row at a time.
The grid below demonstrates inline editing with specialized column editors: ComboBox for categories, SpinEdit for numeric values, DateEdit for dates, and CheckBox for boolean fields.
Inline editing requires three settings:
1. Mode = GridViewEditingMode.Inline
2. CommandColumn with ShowEditButton and ShowDeleteButton
3. UpdateRouteValues pointing to a controller action
that accepts MVCxGridViewInlineUpdateValues
Each row gets its own Edit/Update/Cancel buttons.
Only one row can be in edit mode at a time.
// View configuration:
settings.SettingsEditing.Mode = GridViewEditingMode.Inline;
settings.SettingsEditing.UpdateRouteValues = new {
Controller = "DevExpress",
Action = "ProductsInlineUpdate"
};
settings.SettingsBehavior.ConfirmDelete = true;
settings.CommandColumn.Visible = true;
settings.CommandColumn.ShowNewButton = true;
settings.CommandColumn.ShowEditButton = true;
settings.CommandColumn.ShowDeleteButton = true;
// Column with ComboBox editor:
settings.Columns.Add(column => {
column.FieldName = "Category";
column.ColumnType = MVCxGridViewColumnType.ComboBox;
var props = column.PropertiesEdit as ComboBoxProperties;
props.DataSource = GetCategories();
props.TextField = "Name";
props.ValueField = "Name";
});
[HttpPost]
public ActionResult ProductsInlineUpdate(
MVCxGridViewInlineUpdateValues<Product, int> values)
{
var model = GetProducts();
foreach (var item in values)
{
if (values.IsValid(item))
{
if (item.ID == 0) // New record
{
item.ID = model.Max(x => x.ID) + 1;
model.Add(item);
}
else // Update existing
{
var target = model.FirstOrDefault(
x => x.ID == item.ID);
if (target != null)
{
target.Name = item.Name;
target.Price = item.Price;
// ... update other fields
}
}
}
}
return PartialView("_ProductsGridPartial", model);
}
The Live Result
|
Step 8: Edit Form Mode (Popup Form Editing)
Instead of editing rows inline, Edit Form mode opens a dedicated form (either inline or in a popup) for data entry. This provides more space for complex forms, better layout control, and a focused editing experience. It's ideal when records have many fields or when you need validation before saving.
This grid demonstrates advanced column types: ComboBox with incremental filtering, DateEdit with calendar controls, SpinEdit with currency formatting, and CheckBox for boolean values.
Edit Form mode uses:
1. Mode = GridViewEditingMode.EditForm
2. EditFormLayoutProperties.ColCount for layout
3. MVCxGridViewEditFormUpdatingValues in controller
The form appears when user clicks Edit or New.
This approach works well with validation rules
and complex data entry scenarios.
// View configuration:
settings.SettingsEditing.Mode = GridViewEditingMode.EditForm;
settings.SettingsEditing.EditFormLayoutProperties.ColCount = 2;
// ComboBox with filtering:
settings.Columns.Add(column => {
column.FieldName = "Department";
column.ColumnType = MVCxGridViewColumnType.ComboBox;
var props = column.PropertiesEdit as ComboBoxProperties;
props.DataSource = departments;
props.IncrementalFilteringMode =
IncrementalFilteringMode.StartsWith;
});
// DateEdit with calendar:
settings.Columns.Add(column => {
column.FieldName = "HireDate";
column.ColumnType = MVCxGridViewColumnType.DateEdit;
var props = column.PropertiesEdit as DateEditProperties;
props.DisplayFormatString = "d";
props.CalendarProperties.ShowTodayButton = true;
});
[HttpPost]
public ActionResult EmployeesEditFormUpdate(
MVCxGridViewEditFormUpdatingValues<Employee> values)
{
var model = GetEmployees();
// Handle new record
if (values.NewItemRowItem != null && values.IsValid)
{
values.NewItemRowItem.ID = model.Max(x => x.ID) + 1;
model.Add(values.NewItemRowItem);
}
// Handle update
if (values.UpdateItem != null && values.IsValid)
{
var target = model.FirstOrDefault(
x => x.ID == values.UpdateItem.ID);
// ... copy properties
}
// Handle delete
if (values.DeleteItem != null)
{
var target = model.FirstOrDefault(
x => x.ID == values.DeleteItem.ID);
if (target != null) model.Remove(target);
}
return PartialView("_EmployeesGridPartial", model);
}
The Live Result
|
Step 9: Grouping and Summary Features
DevExpress GridView supports powerful data grouping out of the box. Users can drag any column header to the group panel to organize data hierarchically. Combined with group summaries and total summaries, this transforms raw data into actionable insights without writing any aggregation code.
This example demonstrates: grouping by multiple columns, group-level summaries (count, average, sum), total footer summaries, custom column templates with color-coded badges, ProgressBar columns, conditional row highlighting, and advanced column formatting.
Grouping and Summaries include:
1. Group by any column (drag header to group panel)
2. Multiple group levels (group by Project, then Priority)
3. Group summaries: Count, Average, Sum per group
4. Total summaries: Footer row with aggregates
5. Custom column templates: Color-coded badges
6. ProgressBar columns for percentage values
7. Conditional row highlighting (overdue tasks)
8. ComboBox columns with predefined values
// Enable grouping:
settings.SettingsBehavior.AllowGroup = true;
settings.SettingsBehavior.AutoExpandAllGroups = true;
// Group summaries:
settings.GroupSummary.Add(
DevExpress.Data.SummaryItemType.Count,
"TaskName"
).DisplayFormat = "Tasks: {0}";
settings.GroupSummary.Add(
DevExpress.Data.SummaryItemType.Average,
"Progress"
).DisplayFormat = "Avg Progress: {0:P0}";
// Total summaries:
settings.TotalSummary.Add(
DevExpress.Data.SummaryItemType.Count,
"TaskName"
).DisplayFormat = "Total Tasks: {0}";
settings.TotalSummary.Add(
DevExpress.Data.SummaryItemType.Sum,
"EstimatedHours"
).DisplayFormat = "Total: {0} hrs";
// Initial grouping:
settings.GroupBy(summary => {
summary.Add("Project", ColumnSortOrder.Ascending);
summary.Add("Priority", ColumnSortOrder.Ascending);
});
Possibilities with grouping:
- Drag/drop columns to group panel by users
- Collapse/expand groups individually
- Custom group headers with templates
- Multiple summaries per group
- Conditional formatting (highlight overdue rows)
- Export grouped data to Excel/PDF
- Combine with filtering and search
- Works with master-detail and editing
The grid below auto-groups by Project and Priority.
Try dragging the AssignedTo column header to the
group panel to add a third grouping level.
The Live Result
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Step 10: Selection and Multi-Select Features
Many business scenarios require users to select multiple records for batch processing—sending emails, updating statuses, generating reports, or exporting selected data. DevExpress provides flexible selection modes: checkbox-based selection, row-click selection, and single-select mode.
This example demonstrates: checkbox column with "select all" on page, row-click selection, client-side selection events, server-side processing of selected records, and display of selected items.
Selection features include:
1. Checkbox column in command column
2. Select All checkbox (per page or all rows)
3. Row-click selection (click to toggle)
4. Single-select mode option
5. Client-side GetSelectedKeysOnPage()
6. Server-side processing via POST
7. Display selected items in detail view
8. Combine with other grid features
// Enable selection:
settings.SettingsBehavior.AllowSelectByRowClick = true;
settings.SettingsBehavior.AllowSelectSingleRowOnly = false;
// Checkbox column:
settings.CommandColumn.Visible = true;
settings.CommandColumn.ShowSelectCheckbox = true;
settings.CommandColumn.SelectAllCheckboxMode =
GridViewSelectAllCheckboxMode.Page;
// Client-side event:
settings.ClientSideEvents.SelectionChanged =
"onProductSelectionChanged";
// JavaScript to handle selection:
function onProductSelectionChanged(s, e) {
var selectedKeys = s.GetSelectedKeysOnPage();
document.getElementById('selectedCount')
.textContent = selectedKeys.length;
}
function processSelectedProducts() {
var grid = gvProductSelection;
var selectedKeys = grid.GetSelectedKeysOnPage();
$.ajax({
url: '/DevExpress/ProcessSelectedProducts',
type: 'POST',
data: { selectedIds: selectedKeys },
traditional: true,
success: function(data) {
$('#selectedItemsResult').html(data);
}
});
}
The Live Result
|
Step 11: Adaptive Grid Layout (Responsive Design)
On desktop screens, a grid with many columns looks great. On tablets and phones, those same columns create a horizontal scroll that makes the grid unusable. DevExpress solves this with adaptive layout mode: the grid automatically hides less important columns on smaller screens and adds a detail button so users can still access the hidden data.
This is a must-have feature for any live DevExpress grid that needs to work across devices. Below you can compare the same product data in two grids: one with adaptive mode enabled and one without. Resize your browser window to see the difference.
Adaptive layout requires these settings:
1. AdaptivityMode = GridViewAdaptivityMode.HideDataCells
Automatically hides columns that don't fit the width.
2. AdaptiveColumnPosition = Last (or First)
Controls which columns are hidden first.
3. AdaptiveDetailColumnCount = 1
Adds a detail button column for accessing hidden data.
4. AllowOnlyOneAdaptiveDetailExpanded = true
Only one row's adaptive detail can be open at a time.
The grid handles everything automatically based on
available width. No media queries or custom CSS needed.
@Html.DevExpress().GridView(settings => {
settings.Name = "gvAdaptive";
settings.KeyFieldName = "ID";
settings.Width = Unit.Percentage(100);
// Enable adaptive layout
settings.SettingsAdaptivity.AdaptivityMode =
GridViewAdaptivityMode.HideDataCells;
settings.SettingsAdaptivity.AdaptiveColumnPosition =
GridViewAdaptiveColumnPosition.Right;
settings.SettingsAdaptivity.AdaptiveDetailColumnCount = 1;
settings.SettingsAdaptivity
.AllowOnlyOneAdaptiveDetailExpanded = true;
settings.Columns.Add("Name");
settings.Columns.Add("Category");
settings.Columns.Add("Price")
.PropertiesEdit.DisplayFormatString = "c";
settings.Columns.Add("Stock");
settings.Columns.Add("IsActive");
settings.Columns.Add("CreatedDate")
.PropertiesEdit.DisplayFormatString = "d";
}).Bind(Model).GetHtml()
// Standard grid without adaptive layout:
// Same columns, same data, but NO adaptive settings.
// On narrow screens, this grid creates a horizontal
// scrollbar instead of hiding columns.
@Html.DevExpress().GridView(settings => {
settings.Name = "gvNonAdaptive";
settings.KeyFieldName = "ID";
settings.Width = Unit.Percentage(100);
// No adaptive settings — columns never hide
settings.Columns.Add("Name");
settings.Columns.Add("Category");
settings.Columns.Add("Price")
.PropertiesEdit.DisplayFormatString = "c";
settings.Columns.Add("Stock");
settings.Columns.Add("IsActive");
settings.Columns.Add("CreatedDate")
.PropertiesEdit.DisplayFormatString = "d";
}).Bind(Model).GetHtml()
Adaptive Grid (Responsive)
This grid uses AdaptivityMode.HideDataCells. Resize your browser to a narrow width and columns will automatically hide, replaced by a detail button.
Standard Grid (Non-Adaptive)
Same data, same columns, but no adaptive layout. On narrow screens, this grid creates a horizontal scrollbar instead.
|
Summary: All DevExpress Grid Editing Modes
Throughout this tutorial, we have demonstrated five distinct approaches to data editing in DevExpress GridView:
| Editing Mode | Best For | User Experience | See In |
|---|---|---|---|
| Batch Editing | Bulk updates, spreadsheet-like editing | Click any cell, tab through, save all at once | Step 5 |
| Inline Editing | Controlled row-by-row updates | Edit one row at a time with Update/Cancel | Step 7 |
| Edit Form | Complex forms with many fields | Dedicated form with layout control | Step 8 |
| Master-Detail | Parent-child data relationships | Expand rows to see related child records | Step 4 |
| Read-Only | Data viewing with sort/filter/export | No editing, focus on data analysis | Steps 2-3 |
| Adaptive Layout | Responsive grids for mobile and tablet | Auto-hides columns, detail button for hidden data | Step 11 |
Each mode has its place in production applications. Many real-world systems use multiple modes in the same application—batch editing for bulk imports, inline editing for quick corrections, edit forms for detailed data entry, and master-detail for hierarchical data exploration.
Frequently Asked Questions About DevExpress Grid Demos
This page provides a complete online DevExpress grid demo with 11 live interactive examples you can try directly in your browser. Each demo covers a different feature: sorting, filtering, batch editing, inline editing, edit form mode, master-detail, grouping, summaries, export to Excel/PDF, selection, and adaptive responsive layout. No installation needed — just scroll through and interact with each live DevExpress grid.
Yes! This page contains multiple samples of DevExpress MVC grids with full source code showing the Model, View, and Controller layers. Each sample is a working live grid you can interact with — click cells to edit, expand rows for master-detail, export data to Excel or PDF, and more. The source code for every sample is available behind the "View Source Code" toggle.
Yes. Every grid on this page is a live DevExpress grid running on a real ASP.NET MVC server. You can sort columns, filter rows, search across all fields, edit cells, add new rows, delete rows, export data to Excel/PDF/CSV, and test all features in real time without installing anything.
DevExpress GridView supports four main editing modes:
- Batch Editing — Spreadsheet-like editing where users modify multiple cells and save all changes at once (demonstrated in Step 5)
- Inline Editing — Row-by-row editing where clicking Edit transforms a row into editable fields (demonstrated in Step 7)
- Edit Form Mode — Opens a dedicated form for data entry with full layout control (demonstrated in Step 8)
- Master-Detail — Expands rows to show related child records in nested grids (demonstrated in Step 4)
Batch editing requires setting SettingsEditing.Mode = GridViewEditingMode.Batch, configuring the BatchUpdateRouteValues, and creating a controller action that accepts MVCxGridViewBatchUpdateValues. See our live batch editing sample in Step 5 above for the complete implementation with working code.
Yes, DevExpress GridView supports powerful data grouping with drag-and-drop column headers, multiple group levels, group-level summaries (count, sum, average, min, max), and total footer summaries. Our live grouping demo in Step 9 shows tasks grouped by Project and Priority with aggregate calculations.
Absolutely. DevExpress provides built-in server-side export methods: GridViewExtension.ExportToXlsx(), ExportToPdf(), ExportToCsv(), ExportToRtf(), and more. These methods respect your column formatting, visibility settings, and sort order. Try the live export buttons in Step 6 to download invoice data in Excel, PDF, or CSV format.
Set the column's ColumnType = MVCxGridViewColumnType.ComboBox (or DateEdit, SpinEdit, CheckBox, ProgressBar) and configure the properties through the column's PropertiesEdit. Our live Edit Form demo in Step 8 shows all these editor types in action with full source code.
The DevExpress adaptive grid automatically hides less important columns on smaller screens and shows a detail button so users can still access hidden data. Enable it with settings.SettingsAdaptivity.AdaptivityMode = GridViewAdaptivityMode.HideDataCells and set AdaptiveColumnPosition to control which columns hide first. See our live adaptive grid comparison in Step 11.
Enable checkbox selection with settings.CommandColumn.ShowSelectCheckbox = true and settings.SettingsBehavior.AllowSelectByRowClick = true. Use GetSelectedKeysOnPage() on the client side to retrieve selected IDs, then POST them to a controller action for server-side processing. See our live selection demo in Step 10.
Need an Expert to Build Your Grid Systems?
With over 10 years of experience in DevExpress development, I can help you build high-performance, secure, and complex grid systems for your business. Whether you are migrating from legacy systems or starting a new project, I provide the end-to-end expertise you need.