2013-03-20 13 views
5

Panoramica: Sto cercando di utilizzare un ViewModel che ha una proprietà che è la classe modello che sto cercando di modificare . Ho visto che il modulo di modifica funziona utilizzando i moduli di modifica dello scaffold MVC quando si modifica un modello direttamente, tuttavia sto cercando di utilizzare un ViewModel che contiene il modello che si sta modificando. Tutto funziona tranne per il salvataggio di un campo che viene visualizzato in DropDownList.MVC 3: DropDownList su Modifica forma per un oggetto che è una proprietà di un ViewModel

Spiegazione: ho tentato di utilizzare le funzionalità di ponteggi MVC 3 per creare un modulo di modifica per un modello. Nel tutorial di MVC Music Store, questo viene fatto per la pagina Modifica di un Album, nel StoreManagerController. All'interno di quella pagina, hanno due menu a discesa per Genere e Artista. Ogni aspetto simile a questo nella vista: -

<div class="editor-label"> 
    @Html.LabelFor(model => model.GenreId, "Genre") 
</div> 
<div class="editor-field"> 
    @Html.DropDownList("GenreId", String.Empty) 
    @Html.ValidationMessageFor(model => model.GenreId) 
</div> 

Per quanto posso dire, questi hanno le loro opzioni compilati nel controller utilizzando il ViewBag.

ViewBag.GenreId = new SelectList(db.Genres, "GenreId", "Name", album.GenreId); 
ViewBag.ArtistId = new SelectList(db.Artists, "ArtistId", "Name", album.ArtistId); 

Lavorare con il modello direttamente

Nel mio codice, sono riuscito a fare lo stesso con un oggetto che viene salvato nel DB tramite Entity Framework.

Modello

public class Season 
{ 
    public int SeasonId { get; set; } 
    public int ClubId { get; set; } 
    public Club Club { get; set; } 
} 

codice nel controller

ViewBag.ClubId = new SelectList(clubs, "ClubId", "Name", season.ClubId); 

View

<div class="editor-label"> 
    @Html.LabelFor(model => model.ClubId, "Club") 
</div> 
<div class="editor-field"> 
    @Html.DropDownList("ClubId", String.Empty) 
    @Html.ValidationMessageFor(model => model.ClubId) 
</div> 

Questo funziona bene.

Lavorare con la vista del modello

Comunque ora mi sono reso conto che la pagina ha bisogno di più il testo visualizzato di quello che è disponibile nel modello sono la modifica. Speravo di creare un modello di vista speciale, con il modello modificato (stagione) e il testo in più che voglio visualizzare.

ViewModel

public class EditSeasonViewModel 
{ 
    public string PlayerName {get; set;} 
    public string SummaryText {get; set;} 
    public int PlayerId {get; set;} 
    public Season season {get; set;} 
} 

ho fatto questo, ha cambiato il controllore di avere metodi HttpGet e HttpPost utilizzare il nuovo ViewModel, cambiato la vista ad accettare il nuovo ViewModel, e ha cambiato i metodi 'EditorFor' tutti nella visualizzare per utilizzare model.season.MyProperty.

codice nel controller

ViewBag.ClubId = new SelectList(clubs, "ClubId", "Name", seasonVM.season.ClubId); 

Codice in vista

<div class="editor-label"> 
    @Html.LabelFor(model => model.season.ClubId, "Club") 
</div> 
<div class="editor-field"> 
    @Html.DropDownList("ClubId", String.Empty) 
    @Html.ValidationMessageFor(model => model.season.ClubId) 
</div> 

Quando il debug del metodo HttpPost, tutti i valori per la stagione correttamente esistono, ad eccezione del valore ClubId che dovrebbe venire dalla DropDropList .

Non ho cambiato affatto DropDownList nella vista dal modo in cui era quando stavamo usando direttamente il modello.

Domanda: La mia domanda è, che cosa devo cambiare per ottenere il ClubId da salvare correttamente quando si utilizza questo nuovo EditSeasonViewModel?

Inoltre, in che modo ViewBag.ClubId nel metodo HttpGet nel controller corrisponde a DropDownList nella vista e quindi è stato restituito il valore al metodo HttpPost?

risposta

9

È la tua dichiarazione DropDownList errata. Prova a modificare:

@Html.DropDownListFor(m => m.season.ClubId, ViewBag.ClubId) 

Ma davvero, si dovrebbe mettere che elenco di selezione nel modello:

public SelectList Clubs { get; set; } 

Poi popolarlo nel controller:

Model.Clubs = new SelectList(clubs, "ClubId", "Name", season.ClubId); 

Poi si può do:

@Html.DropDownListFor(m => m.season.ClubId, Model.Clubs) 
+2

+1 per usare l'helper fortemente tipizzato. La maggior parte delle domande dell'elenco a discesa in [tag: asp.net-mvc] sono il risultato di essere aggrovigliati in ViewBag, aiutanti debolmente tipizzati e problemi di associazione dei modelli. –

+0

@SeanHolmesby Grazie per la modifica :) – mattytommo

+0

@mattytommo - Eccellente. Ha funzionato. Sono andato avanti e ho usato il tuo helper fortemente tipizzato, che, da quello che dice Quarantadue, è un modo migliore per gestire gli elenchi a discesa. Penso di aver capito il processo di tutto adesso. –

3

Evitare l'uso di elementi dinamici come ViewBag/ViewData per trasferire i dati dai metodi di azione alle viste. Passa all'approccio fortemente tipizzato.

Aggiorna il tuo Viewmodel per avere altre 2 proprietà. uno per contenere una collezione di club disponibili e uno per tenere il club selezionato.

public class EditSeasonViewModel 
{ 
    public List<SelectListItem> Clubs { set;get;} 
    public int SelectedClub { set;get;} 

    public string PlayerName {get; set;} 
    public string SummaryText {get; set;} 
    public int PlayerId {get; set;} 
    public Season season {get; set;} 

    public EditSeasonViewModel() 
    { 
     Clubs=new List<SelectListItem>(); 
    } 
} 

Ora nella vostra azione GET, I club e caricarlo al Clubs proprietà.

public ActionResult create(int id) 
{ 
    var vm=new EditSeasonViewModel(); 
    vm.Clubs=GetListOfSelectListItemFromClubsFromSomeWhere(); 
    return View(vm); 
} 

assumendo GetListOfSelectListItemFromClubsFromSomeWhere è un metodo che restituisce un elenco di SelectListItem per i vostri club

public List<SelectListItem> GetListOfSelectListItemFromClubsFromSomeWhere() 
{ 
    // to do : return List<SelectListItem> with Value and Text(ClubId Id & Name) 
} 

e nella vostra vista, utilizzare il metodo Html.DropDownListFor helper

@model EditSeasonViewModel 
@using(Html.Beginform()) 
{ 

    @Html.DropdownlistFor(x=>x.SelectedClub, 
          new SelectList(Model.Clubs,"Value","Text"),"select") 
    <input type="submit" /> 
} 

Quando questo modulo è essere pubblicato, si otterrà l'id del club selezionato nella proprietà SelectedClub del modello pubblicato.

0

Si prega di essere sicuri che nel vostro controller modificare/azione creat, la proprietà è correttamente binded:

public async Task<ActionResult> Edit([Bind(Include = "SeasonId,ClubId, otherproperties"]){ 
// code ... 
} 
Problemi correlati