c# - llenar - MVC5 Razor html.dropdownlist para el conjunto seleccionado cuando el valor está en la matriz
llenar un dropdownlist con razor (3)
Dejo esto en caso de que ayude a alguien más. Tuve un problema muy similar y ninguna de las respuestas me ayudó.
Teníamos una vista de esta línea en la parte superior:
IEnumerable<SelectListItem> exitFromTrustDeed = (ViewData["ExitFromTrustDeed"] as IEnumerable<string>).Select(e => new SelectListItem() {
Value = e,
Text = e,
Selected = Model.ExitFromTrustDeed == e
});
y luego abajo en la vista:
@Html.DropDownListFor(m => m.ExitFromTrustDeed, exitFromTrustDeed, new { @class = "form-control" })
Teníamos una propiedad en mi ViewData con el mismo nombre que el selector para la expresión lambda y, por alguna razón, hace que el menú desplegable se represente sin ninguna opción seleccionada.
Cambiamos el nombre en ViewData a
ViewData["ExitFromTrustDeed2"]
y eso hizo que funcionara como se esperaba.
Aunque extraño.
Estoy desarrollando una aplicación ASP.NET MVC 5, con C # y .NET Framework 4.6.1.
Tengo esta
View
:
@model MyProject.Web.API.Models.AggregationLevelConfViewModel
[...]
@Html.DropDownListFor(m => m.Configurations[0].HelperCodeType, (SelectList)Model.HelperCodeTypeItems, new { id = "Configurations[0].HelperCodeType" })
ViewModel
es:
public class AggregationLevelConfViewModel
{
private readonly List<GenericIdNameType> codeTypes;
private readonly List<GenericIdNameType> helperCodeTypes;
public IEnumerable<SelectListItem> CodeTypeItems
{
get { return new SelectList(codeTypes, "Id", "Name"); }
}
public IEnumerable<SelectListItem> HelperCodeTypeItems
{
get { return new SelectList(helperCodeTypes, "Id", "Name"); }
}
public int ProductionOrderId { get; set; }
public string ProductionOrderName { get; set; }
public IList<Models.AggregationLevelConfiguration> Configurations { get; set; }
public AggregationLevelConfViewModel()
{
// Load CodeTypes to show it as a DropDownList
byte[] values = (byte[])Enum.GetValues(typeof(CodeTypes));
codeTypes = new List<GenericIdNameType>();
helperCodeTypes = new List<GenericIdNameType>();
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);
}
}
}
Y
Models.AggregationLevelConfiguration
es:
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; }
}
Necesito establecer el valor seleccionado en estas propiedades:
public IEnumerable<SelectListItem> CodeTypeItems
{
get { return new SelectList(codeTypes, "Id", "Name"); }
}
public IEnumerable<SelectListItem> HelperCodeTypeItems
{
get { return new SelectList(helperCodeTypes, "Id", "Name"); }
}
Pero no puedo configurarlo en la
new SelectList(codeTypes, "Id", "Name");
o
new SelectList(helperCodeTypes, "Id", "Name");
porque el valor seleccionado está en la matriz
Configurations
: campos
AggregationLevelConfiguration.CodeType
y
AggregationLevelConfiguration.HelperCodeType
.
Creo que tengo que establecer el valor seleccionado en la Vista, pero no sé cómo hacerlo.
¿Cómo puedo configurar los valores seleccionados?
Desafortunadamente,
@Html.DropDownListFor()
comporta de manera un poco diferente a otros ayudantes al representar los controles en un bucle.
Esto se informó anteriormente como un problema en CodePlex (no estoy seguro si es un error o solo una limitación)
Hay 2 opciones para resolver esto para garantizar que se seleccione la opción correcta en función de la propiedad del modelo
Opción 1
(usando un
EditorTemplate
)
Cree un
EditorTemplate
personalizado para el tipo en la colección.
Cree un parcial en
/Views/Shared/EditorTemplates/AggregationLevelConfiguration.cshtml
(tenga en cuenta que el nombre debe coincidir con el nombre del tipo
@model yourAssembly.AggregationLevelConfiguration
@Html.DropDownListFor(m => m.HelperCodeType, (SelectList)ViewData["CodeTypeItems"])
.... // other properties of AggregationLevelConfiguration
y luego en la vista principal, pase la
SelectList
al
EditorTemplate
como
additionalViewData
@using (Html.BeginForm())
{
...
@Html.EditorFor(m => m.Configurations , new { CodeTypeItems = Model.CodeTypeItems })
...
Opción 2
(generar una nueva
SelectList
de
SelectList
en cada iteración y establecer el valor
selectedValue
)
En esta opción, su propiedad
CodeTypeItems
debe ser
IEnumerable<GenericIdNameType>
, no una
SelectList
(o simplemente hacer que
codeTypes
una propiedad pública).
Luego en la vista principal
@Html.DropDownListFor(m => m.Configurations[0].HelperCodeType, new SelectList(Model.CodeTypeItems, "Id", "Name", Model.Configurations[0].HelperCodeType)
Nota al
new { id = "Configurations[0].HelperCodeType"
: no es necesario usar el
new { id = "Configurations[0].HelperCodeType"
- el método
DropDownListFor()
ya generó ese atributo de
id
Escribí esta clase para superar un problema que tenía al seleccionar una opción en una lista de selección html. Espero que esto ayude a alguien.
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<string> @class { get; set; }
public string name { get; set; }
public Boolean required { get; set; }
public string size { get; set; }
public IEnumerable<SelectOption> SelectOptions { get; set; }
public HTMLSelect(IEnumerable<SelectOption> options)
{
}
public HTMLSelect(string id, string name)
{
this.id = id;
this.name = name;
}
public HTMLSelect(string id, string name, bool required, IEnumerable<SelectOption> options)
{
this.id = id;
this.name = name;
this.required = required;
}
private string BuildOpeningTag()
{
StringBuilder text = new StringBuilder();
text.Append("<select");
text.Append(this.id != null ? " id=" + ''"'' + this.id + ''"'' : "");
text.Append(this.name != null ? " name=" + ''"'' + this.name + ''"'' : "");
text.Append(">");
return text.ToString();
}
public string GenerateSelect(IEnumerable<SelectOption> options)
{
StringBuilder selectElement = new StringBuilder();
selectElement.Append(this.BuildOpeningTag());
foreach (SelectOption option in options)
{
StringBuilder text = new StringBuilder();
text.Append("/t");
text.Append("<option value=" + ''"'' + option.Value + ''"'');
text.Append(option.Selected != false ? " selected=" + ''"'' + "selected" + ''"'' + ">" : ">");
text.Append(option.Text);
text.Append("</option>");
selectElement.Append(text.ToString());
}
selectElement.Append("</select");
return selectElement.ToString();
}
}
public class SelectOption
{
public string Text { get; set; }
public Boolean Selected { get; set; }
public string Value { get; set; }
}
}
Y
public IEnumerable<SelectOption> getOrderTypes()
{
List<SelectOption> orderTypes = new List<SelectOption>();
if (this.orderType == "OptionText")
{
orderTypes.Add(new SelectOption() { Value = "1", Text = "OptionText", Selected = true });
} else
{
orderTypes.Add(new SelectOption() { Value = "2", Text = "OptionText2" });
}
}
Y para usarlo:
@{
Login_page.Models.HTMLSelect selectElement = new Login_page.Models.HTMLSelect("order-types", "order-types");
}
@Html.Raw(selectElement.GenerateSelect(Model.getOrderTypes()));