@(Html.DevExtreme().LoadPanel()
.ID("loadPanel")
.Position(p => p.Of("#gridContainer"))
.Visible(false)
)
@(Html.DevExtreme().DataGrid<DevExtreme.NETCore.Demos.Models.Northwind.Order>()
.ID("gridContainer")
.KeyExpr("OrderID")
.ShowBorders(true)
.Pager(p => p.Visible(true))
.RepaintChangesOnly(true)
.LoadPanel(loadPanel => loadPanel.Enabled(false))
.Editing(e => e
.Mode(GridEditMode.Row)
.AllowAdding(true)
.AllowDeleting(true)
.AllowUpdating(true)
)
.Columns(columns => {
columns.AddFor(m => m.OrderID).AllowEditing(false);
columns.AddFor(m => m.ShipName);
columns.AddFor(m => m.ShipCountry);
columns.AddFor(m => m.ShipCity);
columns.AddFor(m => m.ShipAddress);
columns.AddFor(m => m.OrderDate).DataType(GridColumnDataType.Date);
columns.AddFor(m => m.Freight);
})
.OnOptionChanged("onOptionChanged")
.OnSaving("onSaving")
)
<div class="options">
<div class="caption">Options</div>
<div class="option">
<span>Edit Row Key:</span>
<div id="editRowKey">null</div>
</div>
<div class="option">
<span>Changes:</span>
<div id="changes">[]</div>
</div>
</div>
<script>
var dataGrid, loadPanel;
$(function () {
dataGrid = $("#gridContainer").dxDataGrid("instance");
loadPanel = $("#loadPanel").dxLoadPanel("instance");
loadPanel.show();
sendRequest('@Url.RouteUrl(new { controller = "DataGridWebApi", action = "Orders", skip = 700 })')
.always(() => { loadPanel.hide(); })
.done((data) => {
dataGrid.option("dataSource", data);
});
});
function onOptionChanged(e) {
if (e.name === "editing") {
var editRowKey = e.component.option("editing.editRowKey"),
changes = e.component.option("editing.changes");
$("#editRowKey").text(editRowKey === null ? "null" : editRowKey);
changes = changes.map((change) => {
return {
type: change.type,
key: change.type !== "insert" ? change.key : undefined,
data: change.data
};
});
$("#changes").text(JSON.stringify(changes, null, " "));
}
};
function onSaving(e) {
var change = e.changes[0];
if (change) {
e.cancel = true;
loadPanel.show();
e.promise = saveChange(change)
.always(() => { loadPanel.hide(); })
.done((data) => {
var orders = e.component.option("dataSource");
if (change.type === "insert") {
change.data = data;
}
orders = DevExpress.data.applyChanges(orders, [change], { keyExpr: "OrderID" });
e.component.option({
dataSource: orders,
editing: {
editRowKey: null,
changes: []
}
});
});
}
};
function saveChange(change) {
switch (change.type) {
case "insert":
return sendRequest('@Url.RouteUrl(new { controller = "DataGridWebApi", action = "InsertOrder" })', "POST", { values: JSON.stringify(change.data) });
case "update":
return sendRequest('@Url.RouteUrl(new { controller = "DataGridWebApi", action = "UpdateOrder" })', "PUT", { key: change.key, values: JSON.stringify(change.data) });
case "remove":
return sendRequest('@Url.RouteUrl(new { controller = "DataGridWebApi", action = "DeleteOrder" })', "DELETE", { key: change.key });
}
};
function sendRequest(url, method, data) {
var d = $.Deferred();
method = method || "GET";
$.ajax(url, {
method: method,
data: data,
cache: false,
xhrFields: { withCredentials: true }
}).done(function (result) {
d.resolve(method === "GET" ? result.data : result);
}).fail(function (xhr) {
d.reject(xhr.responseJSON ? xhr.responseJSON.Message : xhr.statusText);
});
return d.promise();
};
</script>
using DevExtreme.NETCore.Demos.Models;
using DevExtreme.NETCore.Demos.Models.DataGrid;
using DevExtreme.NETCore.Demos.Models.SampleData;
using Microsoft.AspNetCore.Mvc;
using System.Linq;
namespace DevExtreme.NETCore.Demos.Controllers {
public class DataGridController : Controller {
public ActionResult EditStateManagement() {
return View();
}
}
}
using DevExtreme.AspNet.Data;
using DevExtreme.AspNet.Mvc;
using DevExpress.Utils.Serializing.Helpers;
using DevExtreme.NETCore.Demos.Models.DataGrid;
using DevExtreme.NETCore.Demos.Models.Northwind;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
using System.Linq;
namespace DevExtreme.NETCore.Demos.Controllers.ApiControllers {
[Route("api/[controller]/[action]")]
public class DataGridWebApiController : Controller {
InMemoryNorthwindContext _nwind;
public DataGridWebApiController(NorthwindContext nwind, IHttpContextAccessor httpContextAccessor, IMemoryCache memoryCache) {
_nwind = new InMemoryNorthwindContext(nwind, httpContextAccessor, memoryCache);
}
[HttpGet]
public object Orders(DataSourceLoadOptions loadOptions) {
return DataSourceLoader.Load(_nwind.Orders, loadOptions);
}
[HttpPost]
public IActionResult InsertOrder(string values) {
var newOrder = new Order();
JsonPopulateObjectExtensions.PopulateObject(values, newOrder);
if(!TryValidateModel(newOrder))
return BadRequest(ModelState.GetFullErrorMessage());
_nwind.Orders.Add(newOrder);
_nwind.SaveChanges();
return Ok(newOrder);
}
[HttpPut]
public IActionResult UpdateOrder(int key, string values) {
var order = _nwind.Orders.First(o => o.OrderID == key);
JsonPopulateObjectExtensions.PopulateObject(values, order);
if(!TryValidateModel(order))
return BadRequest(ModelState.GetFullErrorMessage());
_nwind.SaveChanges();
return Ok(order);
}
[HttpDelete]
public void DeleteOrder(int key) {
var order = _nwind.Orders.First(o => o.OrderID == key);
_nwind.Orders.Remove(order);
_nwind.SaveChanges();
}
// additional actions
[HttpGet]
public object OrderDetails(int orderID, DataSourceLoadOptions loadOptions) {
return DataSourceLoader.Load(
from i in _nwind.Order_Details
where i.OrderID == orderID
select new {
Product = i.Product.ProductName,
Price = i.UnitPrice,
i.Quantity,
Sum = i.UnitPrice * i.Quantity
},
loadOptions
);
}
[HttpGet]
public object ShippersLookup(DataSourceLoadOptions loadOptions) {
var lookup = from i in _nwind.Shippers
orderby i.CompanyName
select new {
Value = i.ShipperID,
Text = i.CompanyName
};
return DataSourceLoader.Load(lookup, loadOptions);
}
[HttpGet]
public object CustomersLookup(DataSourceLoadOptions loadOptions) {
var lookup = from i in _nwind.Customers
let text = i.CompanyName + " (" + i.Country + ")"
orderby i.CompanyName
select new {
Value = i.CustomerID,
Text = text
};
return DataSourceLoader.Load(lookup, loadOptions);
}
[HttpPost]
public object Batch([FromBody] List<DataChange> changes) {
foreach(var change in changes) {
Order order;
if(change.Type == "update" || change.Type == "remove") {
var key = Convert.ToInt32(change.Key);
order = _nwind.Orders.First(o => o.OrderID == key);
} else {
order = new Order();
}
if(change.Type == "insert" || change.Type == "update") {
JsonPopulateObjectExtensions.PopulateObject(change.Data.ToString(), order);
if(!TryValidateModel(order))
return BadRequest(ModelState.GetFullErrorMessage());
if(change.Type == "insert") {
_nwind.Orders.Add(order);
}
change.Data = order;
} else if(change.Type == "remove") {
_nwind.Orders.Remove(order);
}
}
_nwind.SaveChanges();
return Ok(changes);
}
}
}
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using System;
using System.Collections.Generic;
namespace DevExtreme.NETCore.Demos.Models.Northwind {
public class InMemoryNorthwindContext : InMemoryDataContext<Order> {
NorthwindContext _nwind;
public InMemoryNorthwindContext(NorthwindContext nwind, IHttpContextAccessor contextAccessor, IMemoryCache memoryCache)
: base(contextAccessor, memoryCache) {
_nwind = nwind;
}
public ICollection<Order> Orders => ItemsInternal;
public DbSet<Customer> Customers => _nwind.Customers;
public DbSet<Order_Detail> Order_Details => _nwind.Order_Details;
public DbSet<Shipper> Shippers => _nwind.Shippers;
protected override IEnumerable<Order> Source => _nwind.Orders;
protected override int GetKey(Order item) => item.OrderID;
protected override void SetKey(Order item, int key) => item.OrderID = key;
}
}
#gridContainer {
height: 440px;
}
.options {
padding: 20px;
margin-top: 20px;
background-color: rgba(191, 191, 191, 0.15);
}
.caption {
margin-bottom: 10px;
font-weight: 500;
font-size: 18px;
}
.option {
margin-bottom: 10px;
}
.option > span {
position: relative;
margin-right: 10px;
}
.option > div {
display: inline-block;
font-weight: bold;
}