2011-04-28 5 views
20

ho quello che sembra (a me comunque) è un problema strano ...problema con MVC EditorFor chiamato modello

ho creato un modello semplice editor per un SelectListItem (SelectListItem.cshtml in ~/Vista/Shared cartella/EditorTemplates), ad esempio:

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

Dove c.Categories è un IEnumerable

Questo ha funzionato bene, ma ho voluto un altro modello per rendere la collezione con un po 'diverso di markup, quindi ho copiato e rinominato la modello di editor, ad esempio, 'CategoryIcons.cshtm 'e invocato come segue:

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

In breve, l'unica differenza è che sto specificando un modello di editor denominato.

Quando apro la pagina, ora ottengo il seguente errore:

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'

modello di dichiarazione del modello, sia in modelli ID:

@model System.Web.Mvc.SelectListItem 

Non capisco il motivo per cui il modello predefinito funziona e il modello nominato no. Qualsiasi aiuto sarebbe apprezzato.

Grazie.

risposta

29

Quando si chiama @Html.EditorFor(c => c.Categories) si torna al modello predefinito per IEnumerable. Questo modello predefinito è fornito dal framework MVC e il suo comportamento è di produrre Html.EditorFor() per ciascun elemento nell'enumerazione. Questo a sua volta emette il modello di editor appropriato per ogni elemento nell'elenco singolarmente - nel tuo caso sono tutte le istanze di SelectListItem, quindi nel primo caso viene utilizzato il modello SelectListItem per ciascun elemento.

Nel secondo caso, impostando in modo esplicito il tuo EditorFor di utilizzare un particolare modello di editor di CategoryIcons, si indica in modo da utilizzare tale modello redattore per la tutta l'enumerazione, invece di permettere l'enumerabile di essere basato su modelli di default, in girare usando il modello per ogni oggetto enumerato.

Non sono ancora sicuro del modo migliore per farlo.

Un approccio potrebbe essere quello di definire un modello CategoryIcons, il cui modello è un esempio di IEnumerable<CategoryIcon> che foreaches semplicemente il Model censimento, ed esegue Html.EditorFor per ogni articolo, con un riferimento esplicito modello di CategoryIcon. Quindi inserisci il modello di editor per articolo in quel modello (CategoryIcon non CategoryIcons). Chiameresti questo facendo @Html.EditorFor(c => c.Categories, "CategoryIcons").

Ho intenzione di dare un'occhiata in giro per vedere se ci sono modi migliori per fare questo, ma spero che questo possa essere utile per ora. Sarebbe bello se i modelli potessero essere parametrizzati, quindi potresti scrivere un modello IEnumerable che prende come argomento il nome del modello da utilizzare per ciascuno dei suoi elementi.

+2

Stavo scrivendo esattamente la stessa risposta, l'unica altra cosa che aggiungerò è che puoi racchiudere 'SelectListItem' con una classe di qualsiasi altro nome e usarlo per ottenere un modello diverso, ma in entrambi i casi, questo è probabilmente un buon posto per chi cerca di aggiungere a MVCContrib per iniziare. –

+1

Grazie per la spiegazione e il consiglio. Ho creato una nuova classe ereditando da SelectListItem e poi creato un nuovo modello per quella classe - funziona perfettamente, ma sembra un sovraccarico non necessario. – Neilski

5

Solo un aggiornamento, mi sono imbattuto in questa domanda cercando di affrontare lo stesso problema me stesso.

Quello che ho finito per fare stava scorrendo ogni istanza della collezione e chiamando l'EdtorFor individualmente, un po 'come questo:

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

Ancora non non è pulita, ma mi piace meglio di ereditare una nuova classe come hai finito per farlo.

(Scusate se la mia C# sintassi è un po 'fuori, scrivo in vb.net)

+0

Grazie a Ben, penso che questa soluzione sia molto più semplice, specialmente se si tratta solo di un'istanza del modello. Questo non era il mio caso, e sentivo che nella mia particolare applicazione la creazione di una nuova classe mi permetteva di aggiungere alcuni metodi e proprietà aggiuntivi ai dati. Un caso di "cavalli per corso" credo - grazie per il tuo post - molto apprezzato. – Neilski

1

Se stai usando EditorFor, non credo che la soluzione loop funzionerà. Sembra che l'utilizzo del modello IEnumerable sia l'unico modo per assegnare gli input del modulo correttamente; se si chiama ripetutamente EditorFor, il modulo <INPUT> avrà lo stesso ID anziché ID indicizzati.

Ho riscontrato questo problema e il solution ha dovuto emettere il modello enumerabile e il ciclo non attraverso gli elementi dell'elenco.

Siamo spiacenti di rendere questa risposta non un commento - non hanno diritti di commento.