我的ViewModel中的IEnumerable不会与EditorForModel一起显示

时间:2012-03-15 16:46:48

标签: razor asp.net-mvc-4 mvc-editor-templates

视图模型

[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

注释

  • 我试图将属性“UIHint”但仍然没有显示任何内容!

问题

我做错了什么?

2 个答案:

答案 0 :(得分:3)

默认情况下,当您使用Html.EditorForModel时,请不要期望将其递归到复杂属性,例如类型为Tipos的{​​{1}}属性。布拉德威尔逊在他的blog post中解释了这一点(更具体地说,在帖子结尾处阅读了浅水潜水与深潜部分)。如果您希望这样做,您将需要为Object类型编写自定义编辑器模板。

另一种可能性是指定模板名称:

IEnumerable<SelectListItem>

另外请记住,@Html.EditorFor(x => x.Tipos, "SelectListItem") 的编辑器模板是错误的,因为您将DropDownListFor绑定到模型作为第一个参数。不要忘记这个帮助器的第一个参数必须是一个标量属性,用于保存选定的值。您需要在视图模型上使用字符串或整数属性。第二个参数代表集合。

关于编辑器模板的另一个重要方面是,当您拥有类型为SelectListItem的属性和名为IEnumerable<T>的编辑器模板时,此编辑器模板必须强类型化为T.cshtml类,而不是与T模板一样IEnumerable<T>。如果您使用UIHint或将模板名称指定为EditorFor帮助程序的第二个参数,则不适用。在这种情况下,模板将被输入到集合中。

回顾一下,您可以实现自定义对象编辑器模板,因为Brad Wilson建议将递归到复杂属性,或者您可以修改SelectListItem.cshtml视图以指定EditorFor每个元素。

答案 1 :(得分:1)

@foreach循环呈现看起来正确的内容,但生成的标记对于每一行的控件都具有相同的ID。它也不会使用模型实例发回可枚举的集合。

有两种方法可以使这项工作成为集合中每个项目的唯一ID,以便集合在回发中保持水分:

<强> 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 can't override EditorTemplate name when used in EditorFor for child object