blazor-devexpress-dot-blazor-dot-dxgrid-a6f82230.md
Fires if validation succeeds after a user saves changes or you call the SaveChangesAsync() method.
Namespace : DevExpress.Blazor
Assembly : DevExpress.Blazor.v25.2.dll
NuGet Package : DevExpress.Blazor
[Parameter]
public EventCallback<GridEditModelSavingEventArgs> EditModelSaving { get; set; }
| Type | Description |
|---|---|
| GridEditModelSavingEventArgs |
An object that contains data for this event.
|
The EditModelSaving event fires when one of the following actions triggers row validation and it succeeds:
EditCell mode, focus leaves the edited row.Handle the event to make final data changes, check access permissions, and post changes to the underlying data source. To continue row editing, set the Cancel event argument to true. The EditModel argument allows you to access an edit model that stores all changes. The IsNew property identifies whether the edit model corresponds to a new or existing data item. The DataItem property returns the processed data item. You can use the CopyChangesToDataItem() method to copy all changed fields including nested properties from the edit model to the data item. This method copies changes regardless of how you make changes: in the event handler, razor code, or business logic.
Grid data should be reloaded after you post updates to the data source in the EditModelSaving event handler. The following scenarios are possible:
Change a Data InstanceChange an instance of a field/property bound to the Data parameter if you post updates to the underlying service (such as a DbContext EF Core). The Grid reloads its data in response to this change. The following code snippet demonstrates this scenario.Keep a Data Instance
Do not change a field/property instance bound to the Data parameter in the following cases:
Add and Remove methods, access elements by indexes, and so on).The Grid refreshes its data after the event handler is executed.
Reload ManuallyYou can call the Grid’s Reload() method in the event handler to reload data manually. In this case, set the Reload event argument to false to prevent unnecessary repeated reload.
Tip
For detailed information on how to enable data editing and use edit-related options, refer to the following topic: Editing and Validation in Blazor Grid.
The following example saves changes to an underlying DbContext EF Core object:
View Example: Bind the Grid to data with Entity Framework Core
@page "/"
@using Microsoft.EntityFrameworkCore
@using BindToData.Models
@inject IDbContextFactory<NorthwindContext> NorthwindContextFactory
@implements IDisposable
<DxGrid Data="Data"
CustomizeEditModel="OnCustomizeEditModel"
EditModelSaving="OnEditModelSaving"
DataItemDeleting="OnDataItemDeleting"
KeyFieldName="EmployeeId">
<Columns>
<DxGridCommandColumn />
<DxGridDataColumn FieldName="FirstName" />
<DxGridDataColumn FieldName="LastName" />
<DxGridDataColumn FieldName="Title" />
<DxGridDataColumn FieldName="HireDate" />
</Columns>
<EditFormTemplate Context="editFormContext">
<DxFormLayout>
<DxFormLayoutItem Caption="First Name:">
@editFormContext.GetEditor("FirstName")
</DxFormLayoutItem>
<DxFormLayoutItem Caption="Last Name:">
@editFormContext.GetEditor("LastName")
</DxFormLayoutItem>
<DxFormLayoutItem Caption="Title:">
@editFormContext.GetEditor("Title")
</DxFormLayoutItem>
<DxFormLayoutItem Caption="Hire Date:">
@editFormContext.GetEditor("HireDate")
</DxFormLayoutItem>
</DxFormLayout>
</EditFormTemplate>
</DxGrid>
@code {
IEnumerable<Employee> Data { get; set; }
NorthwindContext Northwind { get; set; }
protected override async Task OnInitializedAsync() {
Northwind = NorthwindContextFactory.CreateDbContext();
Data = await Northwind.Employees.ToListAsync();
}
void OnCustomizeEditModel(GridCustomizeEditModelEventArgs e) {
if(e.IsNew) {
var editModel = (Employee)e.EditModel;
editModel.EmployeeId = Data.Max(x => x.EmployeeId) + 1;
}
}
async Task OnEditModelSaving(GridEditModelSavingEventArgs e) {
var editModel = (Employee)e.EditModel;
// Assign changes from the edit model to the data item.
if (e.IsNew)
await Northwind.AddAsync(editModel);
else
e.CopyChangesToDataItem();
// Post changes to the database.
await Northwind.SaveChangesAsync();
// Reload the entire Grid.
Data = await Northwind.Employees.ToListAsync();
}
async Task OnDataItemDeleting(GridDataItemDeletingEventArgs e) {
// Remove the data item from the database.
Northwind.Remove(e.DataItem);
await Northwind.SaveChangesAsync();
// Reload the entire Grid.
Data = await Northwind.Employees.ToListAsync();
}
public void Dispose() {
Northwind?.Dispose();
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace BindToData.Models;
public partial class Employee {
public int EmployeeId { get; set; }
[Required]
public string LastName { get; set; } = null!;
[Required]
public string FirstName { get; set; } = null!;
public string? Title { get; set; }
public string? TitleOfCourtesy { get; set; }
public DateTime? BirthDate { get; set; }
public DateTime? HireDate { get; set; }
public string? Address { get; set; }
public string? City { get; set; }
public string? Region { get; set; }
public string? PostalCode { get; set; }
public string? Country { get; set; }
public string? HomePhone { get; set; }
public string? Extension { get; set; }
public byte[]? Photo { get; set; }
public string? Notes { get; set; }
public int? ReportsTo { get; set; }
public string? PhotoPath { get; set; }
public virtual ICollection<Employee> InverseReportsToNavigation { get; } = new List<Employee>();
public virtual Employee? ReportsToNavigation { get; set; }
}
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
namespace BindToData.Models;
public partial class NorthwindContext : DbContext {
public NorthwindContext() {}
public NorthwindContext(DbContextOptions<NorthwindContext> options) : base(options) {}
public virtual DbSet<Employee> Employees { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
}
protected override void OnModelCreating(ModelBuilder modelBuilder) {
modelBuilder.UseCollation("SQL_Latin1_General_CP1_CI_AS");
modelBuilder.Entity<Employee>(entity => {
entity.HasIndex(e => e.LastName, "LastName");
entity.HasIndex(e => e.PostalCode, "PostalCode");
entity.Property(e => e.EmployeeId).HasColumnName("EmployeeID");
entity.Property(e => e.Address).HasMaxLength(60);
entity.Property(e => e.BirthDate).HasColumnType("datetime");
entity.Property(e => e.City).HasMaxLength(15);
entity.Property(e => e.Country).HasMaxLength(15);
entity.Property(e => e.Extension).HasMaxLength(4);
entity.Property(e => e.FirstName).HasMaxLength(10);
entity.Property(e => e.HireDate).HasColumnType("datetime");
entity.Property(e => e.HomePhone).HasMaxLength(24);
entity.Property(e => e.LastName).HasMaxLength(20);
entity.Property(e => e.Notes).HasColumnType("ntext");
entity.Property(e => e.Photo).HasColumnType("image");
entity.Property(e => e.PhotoPath).HasMaxLength(255);
entity.Property(e => e.PostalCode).HasMaxLength(10);
entity.Property(e => e.Region).HasMaxLength(15);
entity.Property(e => e.Title).HasMaxLength(30);
entity.Property(e => e.TitleOfCourtesy).HasMaxLength(25);
entity.HasOne(d => d.ReportsToNavigation).WithMany(p => p.InverseReportsToNavigation)
.HasForeignKey(d => d.ReportsTo)
.HasConstraintName("FK_Employees_Employees");
});
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
using Microsoft.EntityFrameworkCore;
// ...
builder.Services.AddDbContextFactory<NorthwindContext>((sp, options) => {
var env = sp.GetRequiredService<IWebHostEnvironment>();
var dbPath = Path.Combine(env.ContentRootPath, "Northwind.db");
options.UseSqlite("DataSource=" + dbPath);
});
Run Demo: Grid - Edit Data View Example: Display an error message from the Web API Service
View Example: Create and edit unbound columns
See Also