Проблема с MVC EditorFor named template

У меня есть то, что появляется (для меня все равно), чтобы быть странной проблемой...

Я создал простой шаблон редактора для SelectListItem (SelectListItem.cshtml в папке ~/Views/Shared/EditorTemplates), например:

<ul class="select-list-item cell-15 col-3 omega clearfix">
    @Html.EditorFor(c => c.Categories)
</ul>

Где c.Categories является IEnumerable

Это сработало хорошо, но я хотел, чтобы другой шаблон отображал коллекцию с немного другой разметкой, поэтому я скопировал и переименовал шаблон редактора, например, в "CategoryIcons.cshtm" и вызывается следующим образом:

<ul class="select-list-item cell-15 col-3 omega clearfix">
    @Html.EditorFor(c => c.Categories, "CategoryIcons")
</ul>

Короче говоря, единственное различие заключается в том, что я указываю шаблон с именованным редактором.

Когда я открываю страницу, я получаю следующую ошибку:

Элемент модели, переданный в словарь, имеет тип "System.Collections.Generic.List`1 [System.Web.Mvc.SelectListItem]", но для этого словаря требуется элемент модели типа "System.Web.Mvc. SelectListItem

Объявление модели шаблона в обоих шаблонах id:

@model System.Web.Mvc.SelectListItem

Я не понимаю, почему работает шаблон по умолчанию, а именованный шаблон - нет. Любая помощь будет оценена.

Спасибо.

Ответ 1

Когда вы вызываете @Html.EditorFor(c => c.Categories), он возвращается к шаблону по умолчанию для IEnumerable. Этот шаблон по умолчанию предоставляется структурой MVC, и его поведение заключается в выводе Html.EditorFor() для каждого элемента в перечислении. Это, в свою очередь, испускает подходящий шаблон редактора для каждого элемента в списке индивидуально - в вашем случае все экземпляры SelectListItem, поэтому в первом случае для каждого элемента используется шаблон SelectListItem.

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

Я еще не уверен в этом.

Один из подходов заключался бы в определении шаблона CategoryIcons, модель которого представляет собой экземпляр IEnumerable<CategoryIcon>, который просто запрашивает перечисление Model и выполняет Html.EditorFor для каждого элемента с явной ссылкой на шаблон CategoryIcon. Затем вы помещаете шаблон шаблона для каждого элемента в этот шаблон (CategoryIcon not CategoryIcons). Тогда вы вызовете это, выполнив @Html.EditorFor(c => c.Categories, "CategoryIcons").

Я собираюсь посмотреть, есть ли лучшие способы сделать это, но я надеюсь, что это может быть полезно сейчас. Было бы здорово, если бы шаблоны могли быть параметризованы, поэтому вы могли бы написать шаблон IEnumerable, который принимает в качестве аргумента имя шаблона для каждого из своих элементов.

Ответ 2

Просто обновление, я наткнулся на этот вопрос, пытаясь решить ту же проблему самостоятельно.

То, что я закончил, - это повторение каждого экземпляра коллекции и вызов EdtorFor в отдельности, например:

<ul class="select-list-item cell-15 col-3 omega clearfix">
    @for (int i=0;i<Model.Categories.Count;i++) {
        @Html.EditorFor(c => c.Categories[i], "CategoryIcons")
    }
</ul>

По-прежнему не чист, но мне это нравится лучше, чем наследование нового класса, как вы делали.

(Извините, если мой синтаксис С# немного выключен, я пишу в vb.net)

Ответ 3

Если вы используете EditorFor, я не думаю, что решение цикла будет работать. Похоже, что использование шаблона IEnumerable является единственным способом правильного имени входов формы; если вы просто назовете EditorFor несколько раз, то ваша форма <INPUT> будет иметь тот же идентификатор, а не индексированные идентификаторы.

У меня возникла эта проблема, а решение должно было испускать перечислимый шаблон и цикл не через элементы списка.

Извините, что этот ответ не является комментарием - не имеют комментариев.