MVC5 Razor html.dropdownlistfor conjunto selecionado quando o valor está na matriz

Estou desenvolvendo um aplicativo ASP.NET MVC 5, com C # e .NET Framework 4.6.1.

Eu tenho esta View :

 @model MyProject.Web.API.Models.AggregationLevelConfViewModel [...] @Html.DropDownListFor(m => m.Configurations[0].HelperCodeType, (SelectList)Model.HelperCodeTypeItems, new { id = "Configurations[0].HelperCodeType" }) 

O ViewModel é:

 public class AggregationLevelConfViewModel { private readonly List codeTypes; private readonly List helperCodeTypes; public IEnumerable CodeTypeItems { get { return new SelectList(codeTypes, "Id", "Name"); } } public IEnumerable HelperCodeTypeItems { get { return new SelectList(helperCodeTypes, "Id", "Name"); } } public int ProductionOrderId { get; set; } public string ProductionOrderName { get; set; } public IList Configurations { get; set; } public AggregationLevelConfViewModel() { // Load CodeTypes to show it as a DropDownList byte[] values = (byte[])Enum.GetValues(typeof(CodeTypes)); codeTypes = new List(); helperCodeTypes = new List(); for (int i = 0; i < values.Length; i++) { GenericIdNameType cType = new GenericIdNameType() { Id = values[i].ToString(), Name = EnumHelper.GetDescription((CodeTypes)values[i]) }; if (((CodeTypes)values[i]) != CodeTypes.NotUsed) codeTypes.Add(cType); helperCodeTypes.Add(cType); } } } 

E o Models.AggregationLevelConfiguration é:

 public class AggregationLevelConfiguration { public byte AggregationLevelConfigurationId { get; set; } public int ProductionOrderId { get; set; } public string Name { get; set; } public byte CodeType { get; set; } public byte HelperCodeType { get; set; } public int PkgRatio { get; set; } public int RemainingCodes { get; set; } } 

Eu preciso definir o valor selecionado nessas propriedades:

 public IEnumerable CodeTypeItems { get { return new SelectList(codeTypes, "Id", "Name"); } } public IEnumerable HelperCodeTypeItems { get { return new SelectList(helperCodeTypes, "Id", "Name"); } } 

Mas eu não posso configurá-lo em new SelectList(codeTypes, "Id", "Name"); ou new SelectList(helperCodeTypes, "Id", "Name"); porque o valor selecionado está na matriz Configurations : campos AggregationLevelConfiguration.CodeType e AggregationLevelConfiguration.HelperCodeType .

Eu acho que tenho que definir o valor selecionado na visão, mas não sei como fazê-lo.

Como posso definir os valores selecionados?

Infelizmente, o @Html.DropDownListFor() se comporta de maneira um pouco diferente de outros auxiliares ao renderizar controles em um loop. Isso foi relatado anteriormente como um problema no CodePlex (não tenho certeza se é um bug ou apenas uma limitação)

A opção é 2 para resolver isso para garantir que a opção correta seja selecionada com base na propriedade do modelo

Opção 1 (usando um EditorTemplate )

Crie um EditorTemplate personalizado para o tipo na coleção. Crie uma parcial em /Views/Shared/EditorTemplates/AggregationLevelConfiguration.cshtml (observe que o nome deve corresponder ao nome do tipo

 @model yourAssembly.AggregationLevelConfiguration @Html.DropDownListFor(m => m.HelperCodeType, (SelectList)ViewData["CodeTypeItems"]) .... // other properties of AggregationLevelConfiguration 

e, em seguida, na visualização principal, passe o SelectList para o EditorTemplate como additionalViewData

 @using (Html.BeginForm()) { ... @Html.EditorFor(m => m.Configurations , new { CodeTypeItems = Model.CodeTypeItems }) ... 

Opção 2 (gerar uma nova SelectList em cada iteração e definir o selectedValue )

Nesta opção, sua propriedade CodeTypeItems deve ser IEnumerable , não uma SelectList (ou apenas tornar codeTypes uma propriedade pública). Então na visão principal

 @Html.DropDownListFor(m => m.Configurations[0].HelperCodeType, new SelectList(Model.CodeTypeItems, "Id", "Name", Model.Configurations[0].HelperCodeType) 

Nota: não há necessidade de usar o new { id = "Configurations[0].HelperCodeType" – o método DropDownListFor() já gerou esse atributo id

Eu escrevi essa class para superar um problema que estava tendo com a seleção de uma opção em uma lista de seleção de html. Eu espero que isso ajude alguém.

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web; namespace Login_page.Models { public class HTMLSelect { public string id { get; set; } public IEnumerable @class { get; set; } public string name { get; set; } public Boolean required { get; set; } public string size { get; set; } public IEnumerable SelectOptions { get; set; } public HTMLSelect(IEnumerable options) { } public HTMLSelect(string id, string name) { this.id = id; this.name = name; } public HTMLSelect(string id, string name, bool required, IEnumerable options) { this.id = id; this.name = name; this.required = required; } private string BuildOpeningTag() { StringBuilder text = new StringBuilder(); text.Append(""); return text.ToString(); } public string GenerateSelect(IEnumerable options) { StringBuilder selectElement = new StringBuilder(); selectElement.Append(this.BuildOpeningTag()); foreach (SelectOption option in options) { StringBuilder text = new StringBuilder(); text.Append("\t"); text.Append(""); selectElement.Append(text.ToString()); } selectElement.Append(" 

E

 public IEnumerable getOrderTypes() { List orderTypes = new List(); if (this.orderType == "OptionText") { orderTypes.Add(new SelectOption() { Value = "1", Text = "OptionText", Selected = true }); } else { orderTypes.Add(new SelectOption() { Value = "2", Text = "OptionText2" }); } } 

E para usá-lo:

 @{ Login_page.Models.HTMLSelect selectElement = new Login_page.Models.HTMLSelect("order-types", "order-types"); } @Html.Raw(selectElement.GenerateSelect(Model.getOrderTypes()));