MVC项目中如何将Kendo Grid数据与表单数据提交至控制器
问题
我在cshtml页面中使用了Kendo Grid,页面同时包含文本框和下拉组合框。部分网格单元格支持编辑,另有部分单元格基于用户输入的数据计算得出。我需要将网格数据以及其他文本框、下拉组合框的值一同提交至控制器。页面上有一个按钮,点击时会执行JavaScript函数,该函数会构建包含文本框和下拉框数据的对象并通过AJAX发送至控制器。
以下是网格的基础代码:
@(Html.Kendo().Grid<TaxCertApp.ViewModels.SettlementMemoViewModel>() .Name("SettlementMemodGrid") .Columns(columns => { columns.Bound(nr => nr.TaxYear).Width(50).Title("Tax Year"); columns.Bound(nr => nr.OriginalAssessment).Width(100).Title("ORIG. ASSESSMENT").Format("{0:##########0}"); columns.Bound(nr => nr.Reduction).Width(100).Title("REDUCTION").EditorTemplateName("Integer").EditorViewData(new { blurHandler = "computeFinalAssessment" }); columns.Bound(nr => nr.FinalAssessment).Width(100).Title("FINAL ASSESSMENT").Format("{0:###,###,##0}"); columns.Bound(nr => nr.Rate).Width(100).Title("RATE").EditorTemplateName("Currency"); columns.Bound(nr=> nr.RefundSavings).Width(100).Title("REFUND/SAVINGS").Format("{0:###,###,##0}"); columns.Bound(e => e.Type).Width(100).EditorTemplateName("TypeList").Title("TYPE (R S R/S)"); }) .Editable(editable => editable.Mode(GridEditMode.InCell)) .Pageable() .Scrollable() .Events(e => e.Edit("OnEdit")) .Events(ev => ev.Change("OnChange")) .DataSource(dataSource => dataSource .Ajax() .Batch(true) .ServerOperation(false) .Model(model => { model.Id(n => n.TaxYear); model.Field(n => n.OriginalAssessment).Editable(false); model.Field(n => n.Reduction).Editable(true); model.Field(n => n.FinalAssessment).Editable(false); model.Field(n => n.Rate).Editable(true); model.Field(n => n.RefundSavings).Editable(true); model.Field(n => n.Type).Editable(true); }) .PageSize(20) .Read(read => { read.Action("FetchSettlementMemoGrid", "Forms").Data("BuildObjectGridSettMemo"); }) ) )
以下是按钮点击触发的JavaScript函数基础代码:
function GenerateSettMemXLS() { var datepicker = $("#SettMemoDateSettled").data("kendoDatePicker"); $('#SettMemoDateNSettledTitle').removeClass('required-field'); if (!ValidateNegRecRequiredFields(datepicker)) { return false; } var combobox = $('#ddlFrmSettMemoCalendarNumber'); var atty = $('ddlFrmSettMemoOurAttorney'); var obj = { ReportType: 'XLS', FileNum: $('#txtFrmSettMemoFileNo').val(), Suffix: $('#ddlFrmSettMemoSuffix').val(), TaxCode: $('#txtFrmSettMemoTaxCode').val(), Class: $('#txtFrmSettMemoClass').val(), CalendarNumber: combobox.data('kendoComboBox').text(), DateSettled: datepicker.value(), AppraisalFee: $('#txtFrmSettMemoAppraisalFee').val(), FDTFee: $('#txtFrmSettMemoFDTFee').val(), ForwardingFee: $('#txtFrmSettMemoForwardingFee').val(), OurAttorney: atty.data('kendoComboBox').text(), RespondentAttorney: $('#txtFrmSettMemoRespondingAttorney').val(), Petitioner: $('#txtSettMemoPetitioner').val(), PropertyAddress: $('#txtSettMemoPropertyAddress').val(), SBL: $('#txtSettMemoSBL').val(), PropertyType: $('#txtSettMemoPropertyType').val(), SchoolDistrict: $('#txtSettMemoSchoolDistrict').val(), }; $.ajax( { url: "/Forms/NegotiationRecordGenerateReport", // Controller/Action contentType: 'application/json; charset=utf-8', datatype: 'json', data: JSON.stringify(obj), type: "POST", success: function (NegotiationRecFileName) { openNegotiationRecordReport(NegotiationRecFileName); }, error: function (XMLHttpRequest, textStatus, errorThrown) { alert("Error retrieving file status "); alert("Error: " + errorThrown); } }); }
我的问题是:如何将网格信息加入到发送至控制器的对象中?
解决方案
要把Kendo Grid的数据整合到提交给控制器的对象里,按以下步骤操作:
获取网格的数据源数据
Kendo Grid的数据源存储了所有当前页面的编辑后数据,通过网格实例的dataSource.data()方法就能拿到完整数据集。在你的JS函数里添加这段代码:// 获取网格实例 var grid = $("#SettlementMemodGrid").data("kendoGrid"); // 获取网格所有数据(包含编辑后的内容),转成JSON格式方便提交 var gridData = grid.dataSource.data().toJSON();把网格数据添加到提交对象
在你构建的obj对象里新增一个属性(比如SettlementMemoData),将上面获取到的gridData赋值给它:var obj = { // 保留原有所有属性 ReportType: 'XLS', FileNum: $('#txtFrmSettMemoFileNo').val(), Suffix: $('#ddlFrmSettMemoSuffix').val(), TaxCode: $('#txtFrmSettMemoTaxCode').val(), Class: $('#txtFrmSettMemoClass').val(), CalendarNumber: combobox.data('kendoComboBox').text(), DateSettled: datepicker.value(), AppraisalFee: $('#txtFrmSettMemoAppraisalFee').val(), FDTFee: $('#txtFrmSettMemoFDTFee').val(), ForwardingFee: $('#txtFrmSettMemoForwardingFee').val(), OurAttorney: atty.data('kendoComboBox').text(), RespondentAttorney: $('#txtFrmSettMemoRespondingAttorney').val(), Petitioner: $('#txtSettMemoPetitioner').val(), PropertyAddress: $('#txtSettMemoPropertyAddress').val(), SBL: $('#txtSettMemoSBL').val(), PropertyType: $('#txtSettMemoPropertyType').val(), SchoolDistrict: $('#txtSettMemoSchoolDistrict').val(), // 新增网格数据属性 SettlementMemoData: gridData };后端控制器接收数据
在后端创建一个接收模型,包含原有属性和网格数据的集合:public class SettlementMemoSubmissionModel { public string ReportType { get; set; } public string FileNum { get; set; } public string Suffix { get; set; } public string TaxCode { get; set; } public string Class { get; set; } public string CalendarNumber { get; set; } public DateTime? DateSettled { get; set; } public string AppraisalFee { get; set; } public string FDTFee { get; set; } public string ForwardingFee { get; set; } public string OurAttorney { get; set; } public string RespondentAttorney { get; set; } public string Petitioner { get; set; } public string PropertyAddress { get; set; } public string SBL { get; set; } public string PropertyType { get; set; } public string SchoolDistrict { get; set; } // 网格数据集合,类型与你的ViewModel一致 public List<SettlementMemoViewModel> SettlementMemoData { get; set; } }然后修改控制器的Action方法参数为这个模型:
[HttpPost] public ActionResult NegotiationRecordGenerateReport(SettlementMemoSubmissionModel submission) { // 处理提交的数据,包括submission.SettlementMemoData // ...业务逻辑代码 }额外注意点
- 你的网格已经设置了
ServerOperation(false),所以dataSource.data()能拿到当前页的所有数据;如果需要全量数据,要确保数据源已经加载了所有页的数据,或者在提交前调用grid.dataSource.read()同步数据。 - 对于计算得出的单元格(比如
FinalAssessment),要确保computeFinalAssessment函数已经把计算值同步到数据源的模型中,避免提交的数据缺失计算结果。
- 你的网格已经设置了
内容的提问来源于stack exchange,提问作者Jonathan Small
相关产品推荐
相关产品推荐

