IEnumerable в моей ViewModel не отображается с EditorForModel - PullRequest
2 голосов
/ 15 марта 2012

ViewModel

[Validator(typeof(ProdutoCategoriaValidator))]
public class ProdutoCategoriaViewModel
{
    [HiddenInput(DisplayValue = false)]
    public Guid ID { get; set; }

    public IEnumerable<SelectListItem> Tipos { get; set; }  // <<<<-------  Is not showing in my view

    [AdditionalMetadata("data-bind", "event: { change: function(data) { Link(data.Nome());  }}")]
    public string Nome { get; set; }

    [DataType(DataType.Url)]
    [AdditionalMetadata("Prefixo", "Produtos/{tipo-de-produto}#")]
    public string Link { get; set; }

    public int? Ordem { get; set; }

    public ProdutoCategoriaViewModel()
    {
        ID = Guid.NewGuid();
    }
}

Решение

Solution explorer

Просмотр (_Formulario.cshtml)

@model ProdutoCategoriaViewModel
@using (Html.BeginForm(null, null, FormMethod.Post, new { id="form-produtocategoria", data_bind = "submit: salvar" }))
{
    @Html.AntiForgeryToken()

    <legend>@Html.MvcSiteMap().SiteMapTitle()</legend>

    <fieldset>
        @Html.ValidationSummary(false, "Verifique os erros abaixo:")
        @Html.EditorForModel()
    </fieldset>

    <div class="buttons">
        @Html.ActionLink("Cancelar", "Index")
        <input type="submit" value="SALVAR" />
    </div>
}

SelectListItem.cshtml

@model IEnumerable<SelectListItem>

@Html.DropDownListFor(m => m, Model)

<p>Test</p>

Результат

Полное изображение: http://i.imgur.com/I7HxA.png

View result

Примечания * * 1023 Я пытался поставить атрибут "UIHint", но все равно ничего не отображается! Вопросы

Что я делаю не так?

Ответы [ 2 ]

3 голосов
/ 15 марта 2012

По умолчанию при использовании Html.EditorForModel не ожидайте, что это приведет к сложным свойствам, таким как ваше свойство Tipos, которое имеет тип IEnumerable<SelectListItem>. Брэд Уилсон объяснил это в своем посте в блоге (более подробно читайте раздел Shallow Dive vs. Deep Dive в конце поста). Вам нужно написать собственный шаблон редактора для типа Object, если вы хотите, чтобы это произошло.

Другая возможность - указать имя шаблона:

@Html.EditorFor(x => x.Tipos, "SelectListItem")

Также имейте в виду, что ваш шаблон редактора для SelectListItem неправильный, потому что вы привязываете DropDownListFor к модели в качестве первого аргумента. Не забывайте, что первый аргумент этого помощника должен быть скалярным свойством, которое будет использоваться для хранения выбранного значения. Для этого вам понадобится строковое или целочисленное свойство в вашей модели представления. Второй аргумент представляет коллекцию.

Другим важным аспектом шаблонов редактора является то, что когда у вас есть свойство типа IEnumerable<T> и шаблон редактора с именем T.cshtml, этот шаблон редактора должен строго типизироваться в класс T, а не IEnumerable<T>, как вы это сделали с вашим SelectListItem.cshtml шаблоном. Это не применяется, если вы используете UIHint или задаете имя шаблона в качестве второго аргумента помощнику EditorFor. В этом случае шаблон будет напечатан в коллекции.

Итак, подведем итог: вы могли бы реализовать собственный шаблон редактора объектов, как предложил Брэд Уилсон, который вернется к сложным свойствам, или вы могли бы изменить представление _Formulario.cshtml, указав Editor для каждого отдельного элемента.

1 голос
/ 02 августа 2013
Цикл

A @foreach отображает что-то, что выглядит правильно , но итоговая разметка будет иметь одинаковый идентификатор для элементов управления каждой строки.Он также не будет публиковать перечисляемую коллекцию обратно с экземпляром модели.

Существует два способа сделать эту работу так, чтобы у вас был уникальный идентификатор для каждого элемента в коллекции, и чтобы коллекция гидратировалась наобратные передачи:

1.Используйте шаблон редактора по умолчанию, а не именованный

// editor name parameter must be omitted; default editor template's model type
// should be a single instance of the child object, not an IEnumerable. This 
// convention looks wrong, but it fully works:
@Html.EditorFor(parentObject => parentObject.Items) 

2.Используйте цикл @for, а не @foreach:

@for (int i = 0; i < parentObject.Items.Count ; i++) {
    // the model binder uses the indexer to disambiguate the collection items' controls: 
    @Html.EditorFor(c => Model.Items[i], "MyEditorTemplate") 
}

Это не будет работать, однако:

// this will error out; the model type will not match the view's at runtime:
@Html.EditorFor(parentObject => parentObject.Items, "MyEditorTemplate")

Также не будет:

@foreach(var item in parentObject.Items) {
    // this will render, but won't post the collection items back with the model instance: 
    @Html.EditorFor(c => item, "MyEditorTemplate") 
}

Для подробного ответа, почему это так, посмотрите на этот вопрос: MVC не может переопределить имя EditorTemplate при использовании в EditorFor для дочернего объекта .

...