我有一个带有CRUD操作的Kendo UI ASP.NET MVC网格,作为表单的一部分提交。在下面的代码片段中,我尝试显示一个列,其中包含一个内联可编辑组合框(绑定到用户名和ID),该组显示用户的名称,但具有用户ID的值。
正确提交表单,但会显示用户ID而不是名称:
columns.ForeignKey(p => p.UserId, (System.Collections.IEnumerable)ViewBag.Users, "SystemUserId", "Name").Title("User").EditorTemplateName("ComboBoxInForm").Visible(true).ClientTemplate("#= UserId #" +
"<input type='hidden' name='Users[#= index(data) #].UserId' value='#= UserId #' />"
);
ComboBoxInForm EditorTemplate:
@model object
@(
Html.Kendo().ComboBoxFor(m => m)
.BindTo((SelectList)ViewData[ViewData.TemplateInfo.GetFullHtmlFieldName("") + "_Data"])
)
如果我删除提供表单输入标记的ClientTemplate,则显示用户的名称而不是用户ID的值,这就是我想要的。但是,我需要将其作为表单的一部分批量提交,因此我无法删除表单输入标记。
无法提交表单(没有输入标记),但是正确显示用户名而不是ID
columns.ForeignKey(p => p.UserId, (System.Collections.IEnumerable)ViewBag.Users, "SystemUserId", "Name").Title("User").EditorTemplateName("ComboBoxInForm").Visible(true);
我可以使用什么解决方案来组合这两个要求,以便网格列显示名称(但具有ID值)并提供表单输入标记?
答案 0 :(得分:1)
首先,ClientTemplate不会覆盖EditorTemplate ...
ClientTemplate本质上是 display 模板,而EditorTemplate则是编辑器模板。
所以,你想要的是ClientTemplate要做的是显示与UserId相关联的名称。
如果你想保持网格的方式(使用ForeignKey和隐藏字段),那么你需要添加一个“映射”功能,将组合框选择的UserId映射到相关名称。
你可以这样做:
剃刀:
.ClientTemplate("#= mapIdToName(UserId) #" +
"<input type='hidden' name='Users[#= index(data) #].UserId' value='#= UserId #' />");
使用Javascript:
function mapIdToName(id) {
var grid = $("#grid").getKendoGrid(),
users = grid.options.columns[0].values,
name;
for (var i = 0; i < users.length; i++) {
if (users[i].value == id) {
name = users[i].text;
break;
}
}
return name;
}
这使用您已拥有的Id-Name数组(通过grid.options.columns.values),该数组由ForeignKey()方法创建。
替代解决方案 。 。 。 。 。 不过,还有其他方法可以达到你想要的效果。
一种方法是不使用ForeignKey,而是将列绑定到包含ID和Name的对象,更具体的EditorTemplate绑定到ForeignKey()所在的同一集合。这不需要映射功能,即:
剃刀:
columns.Bound(x => x.User)
.ClientTemplate("#= User.Name #" +
"<input type='hidden' name='Users[#= index(data) #].UserId' value='#= UserId #' />");
EditorTemplate:
@model object
@(
Html.Kendo().ComboBoxFor(m => m)
.DataValueField("SystemUserId")
.DataTextField("Name")
.BindTo((System.Collections.IEnumerable)ViewBag.Users)
)
隐藏输入法的缺点是必须将网格限制为少量行,因为该技术只能发布单页的数据,因为第2,3页等的数据不会被渲染因此在帖子中没有隐藏的输入。
第三种方式(这是我做事的方式)是根本不使用隐藏的输入。 相反,我使用ajax调用手动发布数据,我首先将“主”表单数据(不是网格数据)序列化为对象(如果使用kendo MVVM,这非常容易),然后将修改后的网格数据与表单合并数据(使用extend)然后发布生成的组合对象。
我使用此技术的变体来序列化网格数据:http://www.telerik.com/support/code-library/save-all-changes-with-one-request
这样做的好处是它支持更大的数据集,因为它可以使用网格分页机制和(这是我喜欢这种技术的主要原因)通过提交带有所有网格/子数据的表单/标题/父数据(在单个请求中,您可以在服务器上同时处理所有数据,从而更好地验证数据的整个“图片”,并允许在单个事务中进行更新支架
答案 1 :(得分:0)
另一个答案from the Telerik forums。
此行为的原因是因为ForeignKey构建器确实提供了将与数值关联的文本显示为内置功能。在引擎盖下,列绑定到仅包含数值的字段。为了在客户端模板中显示文本表示,应编写一些自定义逻辑。我会就如何实现这一目标提供一些指导,以防这对其他面临同样困难的人有所帮助:
columns.values
。这是一个功能正文,其中包含一些注释,可以帮助您说明从与特定数字相关联的columns.values
中找到文本的简单概念(当前字段值):
function textValue(value, fieldName) {
// $("#gridNameId").data("kendoGrid").options.columns contains the
// columns defined in the grid's configuration
// iterate through the array and check the .field value of each column to find
// a column field with same name as the field name parameter (second parameter)
// each column which is defined as "foreign key" does have values array.
// It contains key-value pairs of each values displayed in the combo box.
// return the text value associated with same value as the first first argument (value)
// return text associated with the value
}
ClientTemplate("#= ProductID #" +
"<input type='hidden' name='Products[#= index(data)#].ProductID' value='#= textValue(data.ProductID, \'ProductID\') #' />"