Kendo 嵌套网格在 asp.net MVC 应用程序中扩展行时绑定内部网格
Kendo nested grid bind inner grid when expand the row in asp.net MVC application
我正在实施一个 asp.net MVC 应用程序,其中包含一个带有嵌套数据网格的页面。目前,我正在使用单个复杂数据对象绑定数据并且它正在正确加载数据。
但问题是当内部网格有太多数据时,需要一些时间从数据库中获取数据并为所有行创建一个数据对象。
我需要做的是在用户展开所选行时获取并绑定内部网格数据。
<div class="panel panel-default">
<div class="panel-body">
<div id="purchase-order-grid"></div>
</div>
</div>
$(document).ready(function () {
$("#purchase-order-grid").kendoGrid({
columns: [
{
field: "PurchaseOrderNumber",
title: "Purchase Order",
width: 80,
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
},
{
field: "Store",
title: "Store",
width: 100,
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
}
],
detailTemplate: '<div class="second-level-grid"></div>',
detailInit: function (e) {
e.detailRow.find(".second-level-grid").kendoGrid({
dataSource: e.data.Products,
columns: [
{
field: "PartNumber",
title: "Part",
width: 70
},
{
field: "Description",
title: "Description",
width: 150
}
]
})
},
dataSource: {
type: "json",
transport: {
read: {
url: "@Html.Raw(Url.Action("List", "PurchasingPurchaseOrder"))",
type: "POST",
dataType: "json",
data: additionalData
}
}
}
});
}
function additionalData() {
var data = {
StoreId: $('#@Html.IdFor(model => model.StoreId)').val()
};
addAntiForgeryToken(data);
return data;
}
[HttpPost]
public virtual IActionResult List(PurchaseOrderSearchModel model, DataSourceRequest command)
{
int totalCount = 0;
var purchaseOrder = _purchaseOrderService.GetPurchaseOrdersWithSearchOption(model, out totalCount, command.Page - 1, command.PageSize);
return Json(new DataSourceResult { Data = purchaseOrder, Total = totalCount });
}
我终于找到了解决办法。添加完整代码以供将来参考。
<div class="panel panel-default">
<div class="panel-body">
<div id="purchase-order-grid"></div>
</div>
</div>
var expanded = {};
var grid, id;
$(document).ready(function () {
var element = $("#purchase-order-grid").kendoGrid({
dataSource: {
type: "json",
transport: {
read: {
url: "@Html.Raw(Url.Action("List", "PurchasingPurchaseOrder"))",
type: "POST",
dataType: "json",
data: additionalData
}
},
schema: {
data: "Data",
total: "Total",
errors: "Errors"
},
error: function (e) {
display_kendoui_grid_error(e);
// Cancel the changes
this.cancelChanges();
},
pageSize: @(defaultGridPageSize),
serverPaging: true,
serverFiltering: true,
serverSorting: true
},
sortable: true,
pageable: true,
detailInit: detailInit,
dataBound: function (e) {
grid = this;
grid.tbody.find("tr[role='row']").each(function () {
var id = grid.dataItem(this).PurchaseOrderNumber;
if (expanded.hasOwnProperty(id) && expanded[id]) {
grid.expandRow(this);
}
});
},
detailExpand: function (e) {
id = this.dataItem(e.masterRow).PurchaseOrderNumber;
expanded[id] = true;
},
detailCollapse: function (e) {
id = this.dataItem(e.masterRow).PurchaseOrderNumber;
expanded[id] = false;
},
columns: [
{
field: "Store",
title: "Store",
width: 100,
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
},
{
field: "POCreatedOn",
title: "PO Created On",
width: 100,
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
},
{
field: "SalesOrderTotal",
title: "Sales Order Total",
width: 80,
headerAttributes: { style: "text-align:right" },
attributes: { style: "text-align:right" }
},
{
field: "TotalPOCost",
title: "Total PO Cost (€)",
width: 100,
headerAttributes: { style: "text-align:right" },
attributes: { style: "text-align:right" }
},
{
field: "ShipmentStatus",
title: "Shipment Status",
width: 100,
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
},
{
field: "PaymentStatus",
title: "Payment Status",
width: 90,
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
}
]
});
});
function detailInit(e) {
$("<div/>").appendTo(e.detailCell).kendoGrid({
dataSource: {
type: "json",
transport: {
read: {
url: "@Html.Raw(Url.Action("GetPurchaseOrderByPurchaseOrderNumber", "PurchasingPurchaseOrder"))",
type: "POST",
dataType: "json",
data: nestedGridData(e.data.PurchaseOrderNumber)
}
},
schema: {
data: "Data",
total: "Total",
errors: "Errors"
},
serverPaging: true,
serverSorting: true,
serverFiltering: true,
pageSize: 5,
filter: { field: "PurchaseOrderNumber", operator: "eq", value: e.data.PurchaseOrderNumber }
},
scrollable: false,
sortable: true,
pageable: true,
columns: [
{
field: "Description",
title: "Description",
width: 150
},
{
field: "SalesOrderId",
title: "Order",
width: 80,
template:'#=formatSalesOrderIds(SalesOrderId)#',
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
},
{
field: "QuantityOrdered",
title: "Qty Order",
width: 70,
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
},
{
field: "QuantityDispatched",
title: "Qty Shipped",
width: 70,
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
}
]
});
}
function nestedGridData(purchaseOrderNumber) {
var data = {
GoDirectlyToPurchaseOrderId: purchaseOrderNumber
};
addAntiForgeryToken(data);
return data;
}
public class PurchasingPurchaseOrderController
{
[HttpPost]
public virtual IActionResult List(PurchaseOrderSearchModel model, DataSourceRequest command)
{
int totalCount = 0;
var purchaseOrder = GetPurchaseOrdersWithSearchOption(model, out totalCount, command.Page - 1, command.PageSize);
return Json(new DataSourceResult { Data = purchaseOrder, Total = totalCount
});
}
[HttpPost]
public virtual IActionResult GetPurchaseOrderByPurchaseOrderNumber(PurchaseOrderSearchModel model, DataSourceRequest command)
{
int totalCount = 0;
var products= GetPurchaseOrderByPurchaseOrderNumber(model, out totalCount, command.Page - 1, command.PageSize);
return Json(new DataSourceResult { Data = products, Total = totalCount });
}
}
public class DataSourceRequest
{
public DataSourceRequest()
{
this.Page = 1;
this.PageSize = 10;
}
public int Page { get; set; }
public int PageSize { get; set; }
public List<Sort> Sort { get; set; }
}
我正在实施一个 asp.net MVC 应用程序,其中包含一个带有嵌套数据网格的页面。目前,我正在使用单个复杂数据对象绑定数据并且它正在正确加载数据。
但问题是当内部网格有太多数据时,需要一些时间从数据库中获取数据并为所有行创建一个数据对象。
我需要做的是在用户展开所选行时获取并绑定内部网格数据。
<div class="panel panel-default">
<div class="panel-body">
<div id="purchase-order-grid"></div>
</div>
</div>
$(document).ready(function () {
$("#purchase-order-grid").kendoGrid({
columns: [
{
field: "PurchaseOrderNumber",
title: "Purchase Order",
width: 80,
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
},
{
field: "Store",
title: "Store",
width: 100,
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
}
],
detailTemplate: '<div class="second-level-grid"></div>',
detailInit: function (e) {
e.detailRow.find(".second-level-grid").kendoGrid({
dataSource: e.data.Products,
columns: [
{
field: "PartNumber",
title: "Part",
width: 70
},
{
field: "Description",
title: "Description",
width: 150
}
]
})
},
dataSource: {
type: "json",
transport: {
read: {
url: "@Html.Raw(Url.Action("List", "PurchasingPurchaseOrder"))",
type: "POST",
dataType: "json",
data: additionalData
}
}
}
});
}
function additionalData() {
var data = {
StoreId: $('#@Html.IdFor(model => model.StoreId)').val()
};
addAntiForgeryToken(data);
return data;
}
[HttpPost]
public virtual IActionResult List(PurchaseOrderSearchModel model, DataSourceRequest command)
{
int totalCount = 0;
var purchaseOrder = _purchaseOrderService.GetPurchaseOrdersWithSearchOption(model, out totalCount, command.Page - 1, command.PageSize);
return Json(new DataSourceResult { Data = purchaseOrder, Total = totalCount });
}
我终于找到了解决办法。添加完整代码以供将来参考。
<div class="panel panel-default">
<div class="panel-body">
<div id="purchase-order-grid"></div>
</div>
</div>
var expanded = {};
var grid, id;
$(document).ready(function () {
var element = $("#purchase-order-grid").kendoGrid({
dataSource: {
type: "json",
transport: {
read: {
url: "@Html.Raw(Url.Action("List", "PurchasingPurchaseOrder"))",
type: "POST",
dataType: "json",
data: additionalData
}
},
schema: {
data: "Data",
total: "Total",
errors: "Errors"
},
error: function (e) {
display_kendoui_grid_error(e);
// Cancel the changes
this.cancelChanges();
},
pageSize: @(defaultGridPageSize),
serverPaging: true,
serverFiltering: true,
serverSorting: true
},
sortable: true,
pageable: true,
detailInit: detailInit,
dataBound: function (e) {
grid = this;
grid.tbody.find("tr[role='row']").each(function () {
var id = grid.dataItem(this).PurchaseOrderNumber;
if (expanded.hasOwnProperty(id) && expanded[id]) {
grid.expandRow(this);
}
});
},
detailExpand: function (e) {
id = this.dataItem(e.masterRow).PurchaseOrderNumber;
expanded[id] = true;
},
detailCollapse: function (e) {
id = this.dataItem(e.masterRow).PurchaseOrderNumber;
expanded[id] = false;
},
columns: [
{
field: "Store",
title: "Store",
width: 100,
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
},
{
field: "POCreatedOn",
title: "PO Created On",
width: 100,
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
},
{
field: "SalesOrderTotal",
title: "Sales Order Total",
width: 80,
headerAttributes: { style: "text-align:right" },
attributes: { style: "text-align:right" }
},
{
field: "TotalPOCost",
title: "Total PO Cost (€)",
width: 100,
headerAttributes: { style: "text-align:right" },
attributes: { style: "text-align:right" }
},
{
field: "ShipmentStatus",
title: "Shipment Status",
width: 100,
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
},
{
field: "PaymentStatus",
title: "Payment Status",
width: 90,
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
}
]
});
});
function detailInit(e) {
$("<div/>").appendTo(e.detailCell).kendoGrid({
dataSource: {
type: "json",
transport: {
read: {
url: "@Html.Raw(Url.Action("GetPurchaseOrderByPurchaseOrderNumber", "PurchasingPurchaseOrder"))",
type: "POST",
dataType: "json",
data: nestedGridData(e.data.PurchaseOrderNumber)
}
},
schema: {
data: "Data",
total: "Total",
errors: "Errors"
},
serverPaging: true,
serverSorting: true,
serverFiltering: true,
pageSize: 5,
filter: { field: "PurchaseOrderNumber", operator: "eq", value: e.data.PurchaseOrderNumber }
},
scrollable: false,
sortable: true,
pageable: true,
columns: [
{
field: "Description",
title: "Description",
width: 150
},
{
field: "SalesOrderId",
title: "Order",
width: 80,
template:'#=formatSalesOrderIds(SalesOrderId)#',
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
},
{
field: "QuantityOrdered",
title: "Qty Order",
width: 70,
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
},
{
field: "QuantityDispatched",
title: "Qty Shipped",
width: 70,
headerAttributes: { style: "text-align:center" },
attributes: { style: "text-align:center" }
}
]
});
}
function nestedGridData(purchaseOrderNumber) {
var data = {
GoDirectlyToPurchaseOrderId: purchaseOrderNumber
};
addAntiForgeryToken(data);
return data;
}
public class PurchasingPurchaseOrderController
{
[HttpPost]
public virtual IActionResult List(PurchaseOrderSearchModel model, DataSourceRequest command)
{
int totalCount = 0;
var purchaseOrder = GetPurchaseOrdersWithSearchOption(model, out totalCount, command.Page - 1, command.PageSize);
return Json(new DataSourceResult { Data = purchaseOrder, Total = totalCount
});
}
[HttpPost]
public virtual IActionResult GetPurchaseOrderByPurchaseOrderNumber(PurchaseOrderSearchModel model, DataSourceRequest command)
{
int totalCount = 0;
var products= GetPurchaseOrderByPurchaseOrderNumber(model, out totalCount, command.Page - 1, command.PageSize);
return Json(new DataSourceResult { Data = products, Total = totalCount });
}
}
public class DataSourceRequest
{
public DataSourceRequest()
{
this.Page = 1;
this.PageSize = 10;
}
public int Page { get; set; }
public int PageSize { get; set; }
public List<Sort> Sort { get; set; }
}