Feel free to share demo-related thoughts here.
If you have technical questions, please create a support ticket in the DevExpress Support Center.
Thank you for the feedback!
If you have technical questions, please create a support ticket in the DevExpress Support Center.
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;
}
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.