Ответ 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.