我对MVC
(和Kendo
)相对较新,但我设法使用columns.Group
功能设置了包含多列标题的网格。
@(Html.Kendo().Grid<Result>()
.Name("myGrid")
.Columns(columns =>
{
columns.Bound(c => c.ResultDateTime).Title("Date Time");
foreach (Lot Lot in (Lot[])ViewBag.Lots)
{
columns.Group(group => group
.Title(Lot.LotNumber)
.Columns(info =>
{
info.Bound(Lot.Result.Count.ToString());
info.Bound(Lot.Result.Mean.ToString());
info.Bound(Lot.Result.SD.ToString());
}));
}
columns.Bound(c => c.StandardComment.Description).Title("Comment");
columns.Bound(c => c.ReviewComment.Description).Title("Review Comment");
columns.Command(command => { command.Destroy(); });
})
.Editable(editable => editable
.Mode(GridEditMode.InLine)
.DisplayDeleteConfirmation(true))
.Pageable()
.Navigatable()
.Sortable()
.Groupable()
.Scrollable()
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.PageSize(20)
.ServerOperation(false)
.Events(events => events.Error("error_handler"))
.Read("ResultsAsync_Read", "ResultEntry")
.Destroy("ResultsAsync_Destroy", "ResultEntry")
)
)
正如您所看到的,我正在尝试根据已使用ViewBag
设置和传递的数组动态构建列。
Controller async函数,用于设置ViewBag.Lots
从顶级IEnumerable<Result>
对象中提取数组:
public async Task<ActionResult> ResultsAsync_Read([DataSourceRequest]DataSourceRequest request)
{
IEnumerable<Result> controlSets = await _manager.ReadAsync(test);
ViewBag.Lots = controlSets.Select(x => x.LotResults);
return Json(controlSets.ToDataSourceResult(request));
}
运行此操作时,尝试访问ViewBag.Lots
中的foreach
属性时出现以下错误。
NullReferenceException:未将对象引用设置为的实例 对象
有人知道我为什么会收到此错误,是否有更有效的方法来实现我的目标?
修改
我使用它来保存整个Lot
中可用的最大批量数,而不是使用ViewBag来保存List<Result>
个对象的列表。
我已经在板上接受了@ ken2k的建议,并在控制器的Index()
功能中完成了这项工作:
public async Task<IActionResult> Index()
{
QCTest test = new Models.Acusera.QCTest();
test.TestID = 3;
IEnumerable<Result> controlSets = await _manager.ReadAsync(test);
ViewBag.MaxLots = controlSets.Max(x => x.LotResults.Count);
return View("~/Views/Acusera/DataEntry/ResultEntry.cshtml");
}
然后我循环可用的最大批次数并创建所需的列:
.Columns(columns =>
{
columns.Bound(c => c.ResultDateTime).Title("Date Time");
for (int i = 0; i < ViewBag.MaxLots; ++i)
{
columns.Group(group => group
.Title("Test")
.Columns(info =>
{
info.Bound(x => x.LotResults[i].Result.Count);
info.Bound(x => x.LotResults[i].Result.Mean);
info.Bound(x => x.LotResults[i].Result.SD);
}));
}
columns.Bound(c => c.StandardComment.Description).Title("Comment");
columns.Bound(c => c.ReviewComment.Description).Title("Review Comment");
columns.Command(command => { command.Destroy(); });
})
这会导致网格显示如下:
所以我设法创建了显示数据所需的多个标题列的数量。但是,我现在收到一个错误:
未捕获的TypeError:无法读取属性&#39;结果&#39;未定义的
答案 0 :(得分:2)
您的ResultsAsync_Read
方法是一种异步方法,由Kendo框架从javascript AJAX调用中调用,即在页面加载并呈现后。
这意味着当您的网页呈现时,ViewBag.Lots
实际上为空,这会抛出异常。
您需要在加载页面时初始化此值,而不是在ResultsAsync_Read
方法中。基本上是:
public async Task<ActionResult> Index()
{
// Gets the values BEFORE rendering the view
IEnumerable<Result> controlSets = await _manager.ReadAsync(test);
// The ViewBag property will be available from the Razor view
ViewBag.Lots = controlSets.Select(x => x.LotResults);
// Returns the view that display the grid
return this.View();
}
记住MVC的实际工作方式非常重要。基本上步骤是:
ResultsAsync_Read
,则更改ViewBag 会因页面已呈现而无效。您可以做的唯一修改页面的方法是返回一些JSON,并根据AJAX回调中的JSON结果更改DOM (即使用jQuery / javascript)。