Dropdownlistfor non mostrerà la selezione corretta

Ho tre dropdownlistfor in un ciclo che non mostrano il valore corretto dal DB. Sono sempre predefiniti alla prima voce. Ho controllato e ricontrollato il DB e verificato che dovrebbe essere il secondo nell’elenco. Anche l’elenco è stato creato correttamente. Cosa mi manca?

@foreach (CustomerMeasurementProfile oProfile in Model.Customer.CustomerMeasurementProfiles.Where(m => m.DeletedDate == null)) { 
@Html.Hidden(string.Format("Customer.CustomerMeasurementProfiles[{0}].Id", i), oProfile.Id) @Html.Hidden(string.Format("Customer.CustomerMeasurementProfiles[{0}].CustomerId", i), oProfile.CustomerId) @Html.TextBox(string.Format("Customer.CustomerMeasurementProfiles[{0}].Name", i), oProfile.Name, new { @class = "form-control input-sm" })
@Html.CheckBox(string.Format("DeleteProfiles[{0}]", i), Model.DeleteProfiles[i])
@Html.DropDownListFor(m => oProfile.BodyTypeShoulderId, new SelectList(Model.BodyTypeShoulders, "Id", "Name"), new { @class = "form-control input-sm-select" })
@Html.DropDownListFor(m => oProfile.BodyTypePostureId, new SelectList(Model.BodyTypePosture, "Id", "Name"), new { @class = "form-control input-sm-select" })
@Html.DropDownListFor(m => oProfile.BodyTypeChestId, new SelectList(Model.BodyTypeChest, "Id", "Name"), new { @class = "form-control input-sm-select" })

Se si desidera impostare il valore selezionato che sta entrando in Model . Hai bisogno di farlo in questo modo:

 @Html.DropDownListFor(m => oProfile.BodyTypeShoulderId, new SelectList(Model.BodyTypeShoulders, "Id", "Name", oProfile.BodyTypeShoulderId), new { @class = "form-control input-sm-select" }) 

Il codice precedente imposterà il valore selezionato a discesa su qualunque cosa si trovi nell’object Model corrente BodyTypeShoulderId

Il primo argomento di DropDownListFor indica che al posto del modulo a discesa il valore selezionato verrà mappato con la proprietà Model che è impostata lì (stiamo passando m => oProfile.BodyTypeShoulderId ) ma questo non imposta il valore selezionato.

Per impostare il valore selezionato devi passare il quarto parametro SelectList usando questo overload della class SelectList che è object selectedValue

Sfortunatamente @Html.DropDownListFor() si comporta in modo leggermente diverso dagli altri helper durante il rendering dei controlli in un loop. Per un singolo object

 @Html.DropDownListFor(m => oProfile.BodyTypeShoulderId, new SelectList(Model.BodyTypeShoulders, "Id", "Name")) 

funzionerebbe bene (se il valore di BodyTypeShoulderId corrisponde al valore di una delle opzioni, allora BodyTypeShoulderId sarà selezionata). Ehsan ha mostrato un problema quando lo si utilizza in un ciclo, tuttavia ci sono alcuni altri problemi nel codice, non meno importante è che molte delle proprietà non verranno postate correttamente in una raccolta perché si utilizza un ciclo foreach piuttosto che un for loop (che sta generando il name duplicato e gli attributi id ). SelectList anche una nuova SelectList di SelectList in ogni iterazione del ciclo che non è molto efficiente.

È ansible risolvere entrambi questi e il problema di selezione del menu a discesa utilizzando un EditorTemplate . Supponendo la proprietà CustomerMeasurementProfiles è typeof CustomerMeasurementProfiles , quindi

CustomerMeasurementProfiles.cshtml (aggiungilo a Views/Shared/EditorTemplates o Views/YourController/EditorTemplates )

 @model CustomerMeasurementProfiles @Html.HiddenFor(m => m.ID) @Html.HiddenFor(m => m.CustomerId) .... @Html.DropDownListFor(m => m.BodyTypeShoulderId, (SelectList)ViewData["shoulders"]) .... 

Nel modello di vista, aggiungere le proprietà per la SelectList di selezione e la raccolta filtrata degli elementi da visualizzare

 IEnumerable ActiveCustomerMeasurementProfiles { get; set; } public SelectList BodyTypeShoulderList { get; set; } .... 

e assegnare quei valori nel controller

Quindi nella vista principale

 @using (Html.BeginForm()) { ... @Html.EditorFor(m => m.ActiveCustomerMeasurementProfiles, new { shoulders = Model.BodyTypeShoulderList }) ... 

L’utilizzo di @Html.EditorFor() con una raccolta assegnerà un nome corretto ai controlli (e selezionerà correttamente le opzioni corrette) e sul ActiveCustomerMeasurementProfiles , ActiveCustomerMeasurementProfiles verrà ora ActiveCustomerMeasurementProfiles correttamente con tutte le sue proprietà.