2011-04-28 14 views
20

tengo lo que parece (a mí) a ser un problema extraño ...Problema con MVC EditorFor plantilla llamada

he creado un editor de plantillas simple para un SelectListItem (SelectListItem.cshtml en el directorio ~/Views/Shared/carpeta EditorTemplates), por ejemplo:

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

Dónde c.Categories es un IEnumerable

Esto funcionó bien, pero yo quería otra plantilla para hacer la colección con un poco diferente de marcado, así que copiar y cambió el nombre plantilla de editor para, por ejemplo, 'CategoryIcons.cshtm 'e invocado de la siguiente manera:

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

En resumen, la única diferencia es que estoy especificando una plantilla de editor con nombre.

Al abrir la página, ahora me sale el siguiente error:

The model item passed into the dictionary is of type 'System.Collections.Generic.List`1[System.Web.Mvc.SelectListItem]', but this dictionary requires a model item of type 'System.Web.Mvc.SelectListItem'

modelo de declaración de la plantilla, tanto en las plantillas de Identificación:

@model System.Web.Mvc.SelectListItem 

No entiendo por qué la plantilla predeterminada funciona y la plantilla con nombre no. Cualquier ayuda sería apreciada.

Gracias.

Respuesta

29

Cuando llama al @Html.EditorFor(c => c.Categories), vuelve a la plantilla predeterminada para IEnumerable. Esta plantilla predeterminada es proporcionada por el marco MVC, y su comportamiento es generar Html.EditorFor() para cada elemento en la enumeración. A su vez, emite la plantilla de editor adecuada para cada elemento de la lista individualmente; en su caso, todas son instancias de SelectListItem, por lo que en el primer caso, se usa la plantilla SelectListItem para cada elemento.

En el segundo caso, estableciendo explícitamente su EditorFor usar un editor de plantillas en particular CategoryIcons, le está diciendo a utilizar ese editor de plantillas para el toda enumeración, en lugar de permitir que el enumerables a ser de plantilla por defecto, en gire usando la plantilla para cada artículo enumerado.

No estoy seguro de la mejor manera de evitar esto todavía.

Un enfoque sería definir una plantilla CategoryIcons, cuyo modelo es una instancia de IEnumerable<CategoryIcon>, que simplemente foreaches la enumeración Model, y realiza Html.EditorFor para cada artículo, con una referencia plantilla explícita de CategoryIcon. A continuación, coloca la plantilla del editor por elemento en esa plantilla (CategoryIcon, no CategoryIcons). A continuación, puede llamar a esto haciendo @Html.EditorFor(c => c.Categories, "CategoryIcons").

Voy a echar un vistazo para ver si hay mejores formas de hacerlo, pero espero que esto pueda ser útil por ahora. Sería fantástico si las plantillas se pudieran parametrizar, por lo que podría escribir una plantilla IEnumerable que tome como argumento el nombre de la plantilla que se usará para cada uno de sus elementos.

+2

Estaba escribiendo exactamente la misma respuesta, la única otra cosa que agregaré es que puede ajustar 'SelectListItem' con una clase de cualquier otro nombre y usar eso para obtener una plantilla diferente, pero en cualquier caso, esto es probablemente un buen lugar para alguien que quiera agregar a MVCContrib para comenzar. –

+1

Gracias por la explicación y el consejo. Creé una nueva clase heredando de SelectListItem y luego creé una nueva plantilla para esa clase; funciona perfectamente, pero parece una sobrecarga innecesaria. – Neilski

5

Solo una actualización, me encontré con esta pregunta tratando de resolver el mismo problema yo mismo.

Lo que terminé haciendo fue iteración a través de cada instancia de la colección y llamando a la EdtorFor individual, algo así como esto:

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

aún no está limpia, pero me gusta más que la herencia de una nueva clase como Terminaste haciéndolo.

(Lo siento si mi sintaxis de C# es un poco apagado, escribo en vb.net)

+0

Gracias Ben, creo que esta solución es mucho más fácil, especialmente si solo se trata de una instancia del modelo. Este no fue el caso para mí, y sentí que en mi aplicación particular crear una nueva clase en realidad me permitió agregar algunos métodos y propiedades adicionales a los datos. Supongo que un caso de "caballos por supuesto", gracias por su publicación, fue muy apreciado. – Neilski

1

Si está utilizando EditorFor, no creo que la solución bucle funcionará. Parece que el uso de la plantilla IEnumerable es la única manera para que las entradas de formulario se nombren correctamente; si solo llama a EditorFor repetidamente, su formulario <INPUT> tendrá la misma ID, en lugar de ID indexados.

Experimenté este problema y el solution debía emitir la plantilla enumerable y no recorrer los elementos de la lista.

Disculpa por hacer de esto una respuesta, no un comentario - no tengo derechos para comentar.

Cuestiones relacionadas