在Telerik MVC Grid列定义中,“EditorViewData”是用来做什么的?

13

我有一个如下的Telerik网格:

Html.Telerik().Grid<MatchViewModel>().Name("Matches").Columns(cols =>
             {
                 cols.Bound(e => e.Name);
                 cols.Bound(e => e.Date);
                 cols.Bound(e => e.GuestTeamId);
                 cols.Bound(e => e.HostTeamId);
                 cols.Bound(e => e.PostponedDate);
             ==> cols.Bound(e => e.RefereeId).EditorViewData(new { RefereeName = '' });
                 cols.Bound(e => e.StatusId);
             })

在箭头所指的列中,我想要将裁判名称作为额外数据发送给EditorTemplate。从EditorViewData方法名推断出它可以帮助我实现这一点,但我无法使其正常工作。有人可以帮我解决吗?谢谢。

2个回答

25

如果您的页面有一个明确定义的模型,您不应该使用ViewBag或ViewData,它们会让代码变得混乱。EditorViewData允许您即时创建ViewData,以传递额外的数据给您的EditorTemplate。

例如,假设您希望在网格中的每个项目的EditorTemplate中具有不同的DropDownList值,则需要传递额外的数据来完成此操作。通过EditorViewData,您可以添加来自模型的附加值,以便实现此目的,而无需在控制器中编写任何ViewBag或ViewData对象。

我第一次使用它是在人员网格上,该网格允许编辑添加到嵌套的TabStrip内的Qualifications网格中的已定义资格。关键是我不想让每个人的DropDownList包含他们已经获得的任何资格,像这样...

People Grid

@using Kendo.Mvc.UI
@model PeopleViewModel
@(Html.Kendo().Grid<PersonModel>()
    .Name("PersonGrid")
    .Columns(columns => {
        columns.Bound(b => b.LastName).EditorTemplateName("_TextBox50");
        columns.Bound(b => b.FirstName).EditorTemplateName("_TextBox50");
...
        columns.Command(cmd => { cmd.Edit(); cmd.Destroy(); }).Width(180);
    })
    .ClientDetailTemplateId("personTemplate")
    .ToolBar(toolbar => toolbar.Create())
    .Selectable()
    .Editable(editable => editable.Mode(GridEditMode.InLine))
    .DataSource(dataSource => dataSource
        .Ajax()
        .Model(model =>
            {
                model.Id(a => a.Id);
            })
        .Create(create => create.Action("CreatePerson", "People"))
        .Read(read => read.Action("ReadPeople", "People"))
        .Update(update => update.Action("UpdatePerson", "People"))
        .Destroy(destroy => destroy.Action("DestroyPerson", "People"))
    )
    .Events(events => events.DataBound("dataBound"))
)
<script type="text/javascript">
    function dataBound() {
        this.expandRow(this.tbody.find("tr.k-master-row").first());
    }
</script>
<script id="personTemplate" type="text/kendo-tmpl">
    @(Html.Kendo().TabStrip()
        .Name("TabStrip_#=Id#")
        .Items(items =>
                    {
...
                        items.Add().Text("Edit Qualifications")
                        .LoadContentFrom("PersonQualifications", "People", new {personId = "#=Id#"});
...
                    })
        .ToClientTemplate()
    )
</script>

PeopleViewModel

请忽略继承方面的内容,它超出了本次讨论的范围。但请注意我在所有与此顶层视图相关的子视图上都使用相同的模型。

public class PeopleViewModel : PageViewModel
{
    public int PersonId { get; set; }
    public PersonModel Person { get; set; }
    public IList<QualificationModel> AllQualifications { get; set; }
...

    public PeopleViewModel(BaseViewModel baseViewModel) : base(baseViewModel)
    {}
}

人员资格控制器

数据提供者在其他地方被注入,但请注意 POCO 到 Model 的扁平化——这只是一个将 List 应用于 Model 构造函数的静态方法。

public ActionResult PersonQualifications(int personId)
{
    SetBaseContext(HttpContext);
    var model = new PeopleViewModel(BaseViewModel)
                     {
                        PersonId = personId,
                        AllQualifications = QualificationModel.FlattenToThis(_qualificationDataProvider.Read())
                     };
    return View(model);
}

嵌套的网格(在选项卡条中加载视图)

@using Kendo.Mvc.UI
@model PeopleViewModel
@{
    Layout = null;
}
@(Html.Kendo().Grid<PersonQualificationModel>()
    .Name("QualificationEditGrid_" + Model.PersonId)
    .Columns(columns =>
    {
        columns.ForeignKey(f => f.QualificationId, Model.AllQualifications, "Id", "Display")
===>        .EditorViewData(new {personId = Model.PersonId})
            .EditorTemplateName("PersonQualificationDropDownList");
        columns.Command(cmd =>
                            {
                                cmd.Edit();
                                cmd.Destroy();
                                }).Width(180);
    })
    .ToolBar(toolbar => toolbar.Create())
    .DataSource(dataSource => dataSource
        .Ajax()
        .Events(events => events.Error("error_handler"))
        .Model(model => {
            model.Id(a => a.Id);
        })
        .Create(create => create.Action("CreatePersonQualification", "People"))
        .Read(read => read.Action("ReadPersonQualifications", "People", new {personId = Model.PersonId}))   
        .Destroy(destroy => destroy.Action("DestroyPersonQualification", "People"))
    )
)

EditorTemplate(终于!)

忽略第一个 ViewData 引用,它有助于使此 EditorTemplate 共享。我们感兴趣的是稍微往下的那一个。

@using Kendo.Mvc.UI
@(Html.Kendo().DropDownList()
    .Name(ViewData.TemplateInfo.GetFullHtmlFieldName(""))
    .DataValueField("Id")
    .DataTextField("Name")
    .OptionLabel("Select...")
    .DataSource(dataSource => dataSource
===>    .Read(read => read.Action("ReadDdlQualifications", "People", new {personId = ViewData["personId"]}))
    )
)

控制器方法(仅为了详尽)

public JsonResult ReadDdlQualifications(int personId)
{
    var qualification = _qualificationDataProvider.ReadAvailableToPerson(personId);
    IList<IdNamePair> results = IdNamePair.FlattenToThis(qualification);
    return Json(results, JsonRequestBehavior.AllowGet);
}

显然,这个例子里还有很多其他的东西(希望我留下了足够的代码让它有意义),但是它应该能够传达出需要使用它的时候——并且确实需要。

享受吧。


1
您在EditorViewModel中指定的模型引用了传递的页面级模型。在我的情况下,页面具有主数据,而网格表示详细数据,因此我的DDL选项是在Grid的视图模型中填充的,而不是在页面视图模型中。您如何引用网格的视图模型? - crichavin
我认为我理解你想做什么,每行都有一个下拉菜单,其值取决于该行。不幸的是,以这种方式对此控件的能力似乎是有限的。你可以使用弹出式编辑或ClientDetailTemplate。如果您必须拥有所描述的演示文稿,个人而言,我会放弃Kendo Grid。动态构建表格和任何脚本,然后根据需要将其样式化为Kendo的外观。我也可能会懒惰地使其批量编辑,以便您可以一次看到所有下拉菜单,并在一个大型Ajax表单中同时保存它们,但您也可以逐个进行。 - Trey Gramann

5

我遇到了与Chad相同的问题,正如Trey所提到的,这不能通过传递信息给EditorViewData来完成。无法传递行数据项,只能传递页面数据。

作为替代方案,您可以将此脚本添加到编辑器模板中。然后您可以从网格行中访问字段值并将其传递给数据源调用,基于每一行的数据过滤下拉列表。

<script type="text/javascript">

    function getParentId() {
        var row = $(event.srcElement).closest("tr");
        var grid = $(event.srcElement).closest("[data-role=grid]").data("kendoGrid");
        var dataItem = grid.dataItem(row);
        return { EmployeeId: dataItem.EmployeeId };
    }

</script>

然后将数据项添加到数据源的读取方法中。

@(Html.Kendo().DropDownList()
        .Name("Product")
        .DataValueField("ProductId")
        .DataTextField("ProductName")
        .DataSource(ds => ds
            .Read(read => read.Action("ProductsRead", "Home")
                .Data("getParentId")
                ))
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接