可编辑的详细信息模板 Kendo UI 网格

Posted

技术标签:

【中文标题】可编辑的详细信息模板 Kendo UI 网格【英文标题】:Editable Detail Template Kendo UI Grid 【发布时间】:2012-11-04 11:49:00 【问题描述】:

更新 我已经设法使用值和编辑器模板来呈现表单(见图)。

抱歉,标签涂黑了。保密协议要求...

这现在适用于多行,因为我正在使用该行的 uid 为详细信息模板提供一个唯一的名称:

@(html.Kendo().TabStrip()
    .Name("Details_#=uid#")

我已将下面的源代码更新为最新版本,并列出了我仍然希望得到帮助的问题列表。

突出问题:

保存更改时将详细信息模板与网格一起序列化 使用视图模型上的数据注释分配标签和验证规则(这似乎不起作用,因为我似乎无法让 Html 助手工作。建议很好!

原帖文(源代码已更新)

我正在尝试创建一个批处理网格,其中每个项目都包含一个详细信息模板。

每个详细信息模板都包含一个标签条,我想在其中保存额外的表单数据。

现在,我有标准的批处理网格工作,但我似乎无法在屏幕上获取每个项目的信息并使其可编辑。此外,当存在多于一行时,详细信息模板会中断。模板仍然呈现,但按钮不起作用,因为两个模板具有相同的 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()
)  

【问题讨论】:

【参考方案1】:

    您应该为您的额外信息创建一个模型并将其添加为 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>
    

    保存操作将正常工作。

【讨论】:

以上是关于可编辑的详细信息模板 Kendo UI 网格的主要内容,如果未能解决你的问题,请参考以下文章

Kendo UI - 如何在编辑时使特定字段只读,同时在剑道网格中创建可编辑?

在 Kendo 网格中绑定事件

Kendo ui - 在子添加/编辑时获取父网格项(网格层次结构)

剑道网格弹出显示

Kendo UI:更新一列数据以更改另一列中的值

剑道网格 - 如何在添加/编辑子行时访问父行模型(详细网格)