更新 我已经成功获得带有值和编辑器模板的表单渲染(参见图片)。
抱歉,标签被涂黑了。 NDA 要求...
现在可以跨多行工作,因为我使用行的 uid 为详细信息模板指定一个唯一的名称:
@(Html.Kendo().TabStrip()
.Name("Details_#=uid#")
我已将下面的源代码更新到最新版本,并包含了我仍然希望获得帮助的问题列表。
未解决的问题:
原帖文字(源代码已更新)
我正在尝试创建一个批处理网格,其中每个项目都包含一个详细模板。
每个详细信息模板都包含一个选项卡条,我想在其中保存额外的表单数据。
现在,我可以使用标准批处理网格,但我似乎无法在屏幕上获取每个项目的信息并使其可编辑。此外,当存在多于一行时,详细信息模板会中断。模板仍然会呈现,但按钮不起作用,因为两个模板具有相同的 id,这可以理解地破坏了用户的交互能力,但我不确定如何确保每个行模板的唯一标识符(也许以某种方式使用父 uid?)
完成第一步后,我也不确定如何序列化此表单数据,但如果有必要,我可以为此提出一个单独的问题。
网格
@(Html.Kendo().Grid(Model.ItemModelList)
.Name("ItemGrid")
.Columns(columns =>
{
//Other columns omitted for brevity
columns.Bound(i => i.Description).Width(100);
columns.Command(command =>
{
command.Destroy();
}).Width(60);
})
.ClientDetailTemplateId("ItemDetails")
.ToolBar(toolbar =>
{
toolbar.Create();
toolbar.Save();
})
.Editable(editable => editable.Mode(GridEditMode.InCell).CreateAt(GridInsertRowPosition.Bottom))
.Pageable()
.Sortable()
.Scrollable()
.Resizable(resize => resize.Columns(true))
.DataSource(dataSource => dataSource
.Ajax()
.Batch(true)
.ServerOperation(false)
.Events(events =>
{
events.Error("ItemGrid_ErrorHandler");
})
.Model(model =>
{
model.Id(i => i.ItemModelID);
model.Field(i => i.DimensionUOM).DefaultValue("in");
model.Field(i => i.WeightUOM).DefaultValue("lbs");
})
.Create(create => create.Action("CreateProducts", "ItemGrid"))
.Read(read => read.Action("GetProducts", "ItemGrid"))
.Update(update => update.Action("UpdateProducts", "ItemGrid"))
.Destroy(destroy => destroy.Action("DeleteProducts", "ItemGrid"))
)
)
详细模板
<script id="ItemDetails" type="text/kendo-tmpl">
@(Html.Kendo().TabStrip()
.Name("Details_#=uid#")
.SelectedIndex(0)
.Items(items =>
{
items.Add().Text("test").Content(@<div>
<table id="testForm">
<tr>
<td>TEST</td>
</tr>
<tr>
</tr>
</table>
</div>);
items.Add().Text("test2").Content(@<div>
<table id="test2Form">
<tr>
<td><label>A</label></td>
<td><label>B</label></td>
<td><label>C</label></td>
<td><label>D</label></td>
<td><label>E</label></td>
</tr>
<tr>
<td>
<input class="k-textbox" value="#=objectA#">
</td>
<td>
@(Html.Kendo().DropDownList()
.Name("objectB")
.Value("#=objectB#")
.DataTextField("Text")
.DataValueField("Value")
.BindTo(new SelectList((System.Collections.IEnumerable)ViewBag.objectBListing, "Value", "Value"))
.ToClientTemplate()
)
</td>
<td>
@(Html.Kendo().DropDownList()
.Name("objectC")
.Value("#=objectC#")
.DataTextField("Text")
.DataValueField("Value")
.BindTo(new SelectList((System.Collections.IEnumerable)ViewBag.objectCListing, "Value", "Value"))
.ToClientTemplate()
)
</td>
<td><input class="k-textbox" value="#=objectD#"></td>
<td><input class="k-textbox" value="#=objectE#"></td>
</tr>
</table>
</div>);
})
.ToClientTemplate()
)
您应该为额外信息创建一个模型,并将其添加为 ItemModelList 的属性,如下所示:
public class BaseMode
{
public string UID { get; set; } // Create your own UID, distinguished from Telerik UID by casing.
}
public class ExtraInfoModel : BaseModel
{
[DisplayName("Object A")]
[Required] // For example
public string ObjectA { get; set; }
[DisplayName("Object B")]
[UIHint("DropDownList")]
public int? ObjectB { get; set; }
[DisplayName("Object C")]
public int? ObjectC { get; set; }
public ExtraInfoModel(string uid)
{
this.UID = uid;
}
}
public class ItemModelList : BaseModel
{
public ExtraInfoModel ExtraInfo { get; set; }
public ItemModelList()
{
this.UID = Guid.NewGuid().ToString(); // Not sure about syntax, please review.
this.ExtraInfo = new ExtraInfoModel(this.UID); // Guarantee ExtraInfo.UID is the same as parent UID when you get model from DB.
}
}
在第二个选项卡中使用剑道网格为您的详细额外信息创建部分视图:
@model ExtraInfoModel
@(Html.Kendo().TabStrip()
.Name("Details_#=UID#")
.SelectedIndex(0)
.Items(items =>
{
items.Add().Text("test").Content(@<text>
<div>
<table id="testForm">
<tr>
<td>TEST</td>
</tr>
<tr></tr>
</table>
</div>
</text>);
items.Add().Text("test2").Content(@<text>
@(Html.Kendo().Grid<ExtraInfoModel>()
.Name("gvDetail_#=UID#")
.Columns(c =>
{
c.Bound(m => m.ObjectA).ClientTemplate(Html.Kendo().TextBox()
.Name("ObjectA")
.HtmlAttributes(new { id = "ObjectA_#=UID#" })
.Value(Model.AgencyCode)
.ToClientTemplate()
.ToHtmlString());
c.Bound(m => m.ObjectB).ClientTemplate(Html.Kendo().DropDownList()
.Name("ObjectB")
.HtmlAttributes(new { id = "ObjectB_#=UID#" })
.Value((Model != null && Model.ObjectB.HasValue) ? Model.ObjectB.ToString() : string.Empty)
.OptionLabel("Select B...")
.BindTo(ViewBag.Data)
.ToClientTemplate()
.ToHtmlString());
// Config ObjectC same as ObjectB.
})
.BindTo(new ExtraInfoModel[] { Model }) // Your detail grid has only one row.
)
</text>);
})
)
在主视图页面中,使用服务器详细信息模板而不是客户端详细信息模板。我建议使用服务器模板,因为我在步骤2中使用了服务器绑定。当然,您可以将其更改为ajax绑定或本地绑定(通过定义事件OnDetailExpand)
@Html.Kendo().Grid(Model.ItemModelList)
...
.DetailTemplate(@<text>
@Html.Partial("YourPartialName", item.ExtraInfo) // item stands for ItemModelList, which is the binding data item.
</text>)
最后一个,对于您的第一个问题,在保存时序列化额外信息数据,我们应该处理每个额外信息属性的更改事件,以为主数据项设置值和脏标志。请记住,批量编辑中的剑道网格仅提交脏数据项。回到步骤 2:
c.Bound(m => m.ObjectB).ClientTemplate(Html.Kendo().DropDownList()
.Name("ObjectB")
.HtmlAttributes(new { id = "ObjectB_#=UID#" })
.Value((Model != null && Model.ObjectB.HasValue) ? Model.ObjectB.ToString() : string.Empty)
.OptionLabel("Select B...")
.BindTo(ViewBag.Data)
.Events(e => e.Change("onChangeObjectB")) // Added this line
.ToClientTemplate()
.ToHtmlString());
<script type="text/javascript">
function onChangeObjectB(e) {
var selectedValue = this.value();
var sender = e.sender;
if (sender != undefined && sender.length > 0) {
var detailRow = sender.closest(".k-detail-row");
var masterRow = detailRow.prev();
var mainGrid = $("#ItemGrid").data("kendoGrid");
if (mainGrid != null) {
var masterRowIndex = masterRow.parent().find(".k-master-row").index(masterRow);
var dataItem = mainGrid.dataSource._data[masterRowIndex];
dataItem.ObjectB = selectedValue;
dataItem._dirty = true;
}
}
}
</script>
保存操作将正常进行。