Your search did not match any results.

Real-Time Updates

The DataGrid component is optimized for real-time updates. You should bind it to a DataSource that contains a store and use the push(changes) method to update the store's data. The rows with changed data are rerendered (see the DataGrid's repaintChangesOnly property). The DataSource object also provides properties that control its behavior when it receives a push. For example, reshapeOnPush is set to true in this demo to allow summaries to be recalculated.

Grids in the detail sections are updated in real time as well. All the grids share the same ordersStore that receives pushes, but it is filtered to show only a specific product's orders for each grid.

Backend API
@(Html.DevExtreme().DataGrid() .ID("gridContainer") .DataSource(d => d.Array().Data(new JS("products")).Key("ProductID")) .DataSourceOptions(o => o.ReshapeOnPush(true)) .RepaintChangesOnly(true) .ColumnAutoWidth(true) .ShowBorders(true) .Paging(p => p.PageSize(10)) .Columns(c => { c.Add() .DataField("ProductName") .DataType(GridColumnDataType.String); c.Add() .DataField("UnitPrice") .DataType(GridColumnDataType.Number) .Format(Format.Currency); c.Add() .DataField("OrderCount") .DataType(GridColumnDataType.Number); c.Add() .DataField("Quantity") .DataType(GridColumnDataType.Number); c.Add() .DataField("Amount") .DataType(GridColumnDataType.Number) .Format(Format.Currency); }) .Summary(s => s.TotalItems(totalItems => { totalItems.Add() .SummaryType(SummaryType.Count) .Column("ProductName"); totalItems.Add() .SummaryType(SummaryType.Sum) .DisplayFormat("{0}") .ValueFormat(Format.Currency) .Column("Amount"); totalItems.Add() .SummaryType(SummaryType.Sum) .DisplayFormat("{0}") .Column("OrderCount"); }) ) .MasterDetail(md => { md.Enabled(true); md.Template(@<text> @(Html.DevExtreme().DataGrid() .DataSource(new JS("getDetailGridDataSource(key)")) .RepaintChangesOnly(true) .ColumnAutoWidth(true) .ShowBorders(true) .Paging(p => p.PageSize(5)) .Columns(c => { c.Add() .DataField("OrderID") .DataType(GridColumnDataType.Number); c.Add() .DataField("ShipCity") .DataType(GridColumnDataType.String); c.Add() .DataField("OrderDate") .DataType(GridColumnDataType.DateTime); c.Add() .DataField("UnitPrice") .DataType(GridColumnDataType.Number) .Format(Format.Currency); c.Add() .DataField("Quantity") .DataType(GridColumnDataType.Number); c.Add() .Caption("Amount") .DataType(GridColumnDataType.Number) .Format(Format.Currency) .CalculateCellValue("getAmount") .AllowSorting(true); }) .Summary(s => s.TotalItems(totalItems => { totalItems.Add() .SummaryType(SummaryType.Count) .Column("OrderID"); totalItems.Add() .SummaryType(SummaryType.Sum) .DisplayFormat("{0}") .Column("Quantity"); totalItems.Add() .SummaryType(SummaryType.Sum) .DisplayFormat("{0}") .ValueFormat(Format.Currency) .Column("Amount"); }) ) ) </text>); }) ) <script src="~/Scripts/data/realTimeData.js"></script> <script> function getDetailGridDataSource(key) { return { store: ordersStore, filter: ["ProductID", "=", key], reshapeOnPush: true } } function getAmount(order) { return order.UnitPrice * order.Quantity; } function frequencyChanged(e) { updatesPerSecond = e.value; } var updatesPerSecond = 100; $(function () { var productsStore = $("#gridContainer").dxDataGrid("getDataSource").store(); setInterval(function () { if (orders.length > 500000) { return; } for (var i = 0; i < updatesPerSecond / 20; i++) { addOrder(productsStore); } }, 50); }); </script> <div class="options"> <div class="caption">Options</div> <div class="option"> <span>Update frequency:</span> @(Html.DevExtreme().Slider() .ID("frequency-slider") .Min(10) .Max(5000) .Step(10) .Value(new JS("updatesPerSecond")) .OnValueChanged("frequencyChanged") .Tooltip(t => t .Enabled(true) .ShowMode(SliderTooltipShowMode.Always) .Format("#0 per second") .Position(VerticalEdge.Top) ) ) </div> </div>
using DevExtreme.MVC.Demos.Models; using DevExtreme.MVC.Demos.Models.DataGrid; using DevExtreme.MVC.Demos.Models.SampleData; using System; using System.Linq; using System.Web.Mvc; namespace DevExtreme.MVC.Demos.Controllers { public class DataGridController : Controller { public ActionResult RealTimeUpdates() { return View(); } } }
var cities = ["Los Angeles", "Denver", "Bentonville", "Atlanta", "Reno", "Beaver", "Malibu", "Phoenix", "San Diego", "Little Rock", "Pasadena", "Boise", "San Jose", "Chatsworth", "San Fernando", "South Pasadena", "San Fernando Valley", "La Canada", "St. Louis"]; var orders = []; var ordersStore = new DevExpress.data.ArrayStore({ key: "OrderID", data: orders }); var products = []; for (var i = 1; i <= 100; i++) { products.push({ ProductID: i, ProductName: "Product " + i, UnitPrice: Math.floor(Math.random() * 1000) + 1, Quantity: 0, Amount: 0, OrderCount: 0 }); } function addOrder(productsStore) { var product = products[Math.round(Math.random() * 99)]; var order = { OrderID: orders.length ? orders[orders.length - 1].OrderID + 1 : 20001, ShipCity: cities[Math.round(Math.random() * (cities.length - 1))], ProductID: product.ProductID, UnitPrice: product.UnitPrice, OrderDate: new Date(), Quantity: Math.round(Math.random() * 20) + 1 }; ordersStore.push([{ type: "insert", data: order }]); productsStore.push([{ type: "update", key: order.ProductID, data: { OrderCount: product.OrderCount + 1, Quantity: product.Quantity + order.Quantity, Amount: product.Amount + order.UnitPrice * order.Quantity } }]); }
.options { padding: 20px; margin-top: 20px; background-color: rgba(191, 191, 191, 0.15); } .caption { font-weight: 500; font-size: 18px; } .option { margin-top: 10px; display: flex; align-items: center; } .option > span { position: relative; top: 2px; margin-right: 10px; } .option > .dx-widget { width: 500px; display: inline-block; vertical-align: middle; }