Что такое "EditorViewData" для определения столбца в столбце Telerik MVC?

У меня есть сетка телериков:

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.i, исходя из имени метода EditorViewData, которое может помочь мне сделать это. Но я не могу заставить его работать. Кто-нибудь может мне помочь с этим? спасибо.

Ответ 1

Если у вас есть хорошо определенная модель для вашей страницы, вам никогда не придется использовать ViewBag или ViewData, они неаккуратные. EditorViewData позволяет вам создавать ViewData "на лету", чтобы передавать дополнительные данные на ваш редактор.

Например, скажем, что вы хотите иметь разные значения DropDownList в EditorTemplate для каждого элемента в своей сетке, вам нужно будет передать дополнительные данные для этого. С помощью EditorViewData вы можете добавить дополнительные значения из своей модели точно для этой цели, не прибегая к кодированию любых объектов ViewBag или ViewData в вашем контроллере.

Первое, что я использовал, это сетка People, которая позволила редактировать определенные Квалификации, добавленные в сетку квалификаций внутри вложенного TabStrip. Трюк заключался в том, что я не хотел, чтобы DropDownList для каждого человека содержал какую-либо квалификацию, которую они уже заработали. Как это...

Сетка для людей

@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)
    {}
}

Контроллер PersonQualifications

Поставщики данных вводятся в другое место, но обратите внимание на сглаживание POCO на Model - только статический метод, который применяет конструктор List to the Model.

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

Вложенная сетка (View Loaded Inside TabStrip)

@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"))
    )
)

The 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);
}

Очевидно, что в этом примере много других вещей (я надеюсь, что я оставил достаточно кода для того, чтобы это имело смысл), но он должен переходить к моменту, когда это необходимо - и это ДЕЙСТВИТЕЛЬНО необходимо.

Enjoy.

Ответ 2

Я столкнулся с тем же вопросом, что и Чад, и, как сказал Трей, это невозможно сделать, передав информацию в EditorViewData​​strong > . Невозможно передать элемент данных строки, только данные страницы.

В качестве альтернативы вы можете добавить этот script в шаблон редактора. Затем вы можете получить доступ к значению поля из строки сетки и передать его на вызов источника данных, фильтровать раскрывающийся список на основе данных каждой строки.

<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")
                ))
)