asp.net-mvc - mvc - html.dropdownlist ejemplos
¿Por qué ListBoxFor no selecciona elementos, pero ListBox es? (7)
Aunque esta no es una respuesta a su pregunta principal, vale la pena señalar que cuando MVC genere nombres, convertirá algo así como Project.Tags en Project_Tags, reemplazando los períodos con guiones bajos.
La razón por la que hace esto es porque un período en una ID de elemento se vería como un elemento denominado Proyecto con una clase de Etiquetas para CSS. Claramente, es algo malo, de ahí la traducción que subraya para mantener el comportamiento predecible.
En tu primer ejemplo,
<%= Html.ListBoxFor(c => c.Project.Categories,
new MultiSelectList(Model.Categories, "Id", "Name", new List<int> { 1, 2 }))%>
el cuadro de lista está intentando vincularse a Model.Project.Categories para su modelo fuertemente tipado que se ha proporcionado a la página (utilizando la notación lambda). No estoy seguro de qué está haciendo el segundo parámetro en ListBoxFor.
¿Cuál es el modelo que se está pasando a la página?
Tengo el siguiente código en mi opinión:
<%= Html.ListBoxFor(c => c.Project.Categories,
new MultiSelectList(Model.Categories, "Id", "Name", new List<int> { 1, 2 }))%>
<%= Html.ListBox("MultiSelectList",
new MultiSelectList(Model.Categories, "Id", "Name", new List<int> { 1, 2 }))%>
La única diferencia es que el primer ayudante está fuertemente tipado (ListBoxFor) y no muestra los elementos seleccionados (1,2), aunque los elementos aparezcan en la lista, etc. El ListBox más simple funciona como se esperaba.
Obviamente me falta algo aquí. Puedo usar el segundo enfoque, pero esto realmente me molesta y me gustaría resolverlo.
Como referencia, mi modelo es:
public class ProjectEditModel
{
public Project Project { get; set; }
public IEnumerable<Project> Projects { get; set; }
public IEnumerable<Client> Clients { get; set; }
public IEnumerable<Category> Categories { get; set; }
public IEnumerable<Tag> Tags { get; set; }
public ProjectSlide SelectedSlide { get; set; }
}
Actualizar
Acabo de cambiar el nombre de ListBox a Project.Categories (que coincide con mi modelo) y ahora NO SE PUEDE seleccionar el elemento.
<%= Html.ListBox("Project.Categories",
new MultiSelectList(Model.Categories, "Id", "Name", new List<int> { 1, 2 }))%>
Obviamente no entiendo la magia que está sucediendo aquí.
Actualización 2
Ok, esto es pura denominación, por ejemplo, esto funciona ...
<%= Html.ListBox("Project_Tags",
new MultiSelectList(Model.Tags, "Id", "Name", Model.Project.Tags.Select(t => t.Id)))%>
... porque el nombre del campo es Project_Tags, no Project.Tags, de hecho, cualquier cosa que no sea Tags o Project.Tags funcionará. No entiendo por qué esto podría causar un problema (aparte de que coincide con el nombre de la entidad), y no soy lo suficientemente bueno para poder profundizar y descubrirlo.
Prueba esto
<%= Html.ListBoxFor(c => c.Project.Categories,
new MultiSelectList(
Model.Categories
,"Id"
,"Name"
,Model.Project.Tags.Select(
x => new SelectListItem()
{
Selected = true,
Text = x.TEXT,
Value = x.ID.ToString()
}).ToList())
)
)%>
Además, puede intentar borrar ModelState para c.Project.Categories en el controlador:
[HttpPost]
public ActionResult Index(ModelType model)
{
ModelState.Remove("Project.Categories");
return View("Index", model);
}
Y usa la siguiente construcción:
<%= Html.ListBoxFor(c => c.Project.Categories,
new MultiSelectList(Model.Categories, "Id", "Name"))%>
Donde c.Project.Categories es IEnumerable<int>
.
Lo siento por mi ingles. ¡Buena suerte!
Html.ListboxFor y Html.Listbox funcionan muy bien cuando NO estás vinculando el cuadro de lista a su origen de datos. Supongo que el uso previsto es este:
// Model
public class ListBoxEditModel
{
public IEnumerable<Category> Categories { get; set; }
public IEnumerable<Category> SelectedCategories { get; set; }
}
En la vista:
@Html.ListBoxFor(m => m.SelectedCategories,
new MultiSelectList(Model.Categories, "Id", "Name"))
// or, equivalently
@Html.ListBox("SelectedCategories" ,
new MultiSelectList(Model.Categories, "Id", "Name"))
Tenga en cuenta que en este caso no tiene que indicar explícitamente qué valores se seleccionan en MultiSelectList: el modelo al que se está vinculando tiene prioridad, ¡incluso si lo hace!
La respuesta correcta es que no funciona muy bien. Como tal, leo el código MVC. Lo que debe hacer es implementar IConvertible y también crear un TypeConverter.
Entonces, en mi caso, tenía una clase de Country
, de modo que las personas podían elegir de una lista de países. No hay alegría en seleccionarlo. Esperaba que un objeto sea igual a la comparación en los artículos selectedItems
en comparación con los elementos de lista, pero no, así no es como funciona. A pesar de que MultiListItem
funciona correctamente y obtiene los elementos seleccionados, en el momento en que está vinculado a su modelo, todo se basa en comprobar que la represión de cadena de su instancia de objeto coincide con el "value"
cadena (o el nombre si falta) en el lista de elementos en SelectItemList
.
Por lo tanto, implemente IConvertible
, devuelva el valor de cadena de ToString
que coincidiría con el valor en SelectItemList
. por ejemplo, en mi caso CountryCode
se serializó en la propiedad Value
SelectItem
, por lo que en ToString IConvertible
CountryCode
. Ahora todo selecciona correctamente.
TypeConverter
el TypeConverter
se usa en el camino hacia adentro. Esta vez es el inverso. Ese Countrycode
regresa y "EN" necesita convertirse en instancia de clase Country
. Ahí es donde entró el TypeConverter
. También es el momento en que me di cuenta de lo difícil que es usar este enfoque.
ps así que en su clase de Category
necesita implementar IConvertible
. Si es del marco de la entidad como mi empresa, entonces necesitarás usar la clase parcial para implementar IConvertible
e implementar ToString
y decorarlo con un TypeConverter
que también escribiste.
Me encontré con este problema yo mismo, finalmente me di cuenta de que el problema era una convención de nombres.
No puede nombrar la propiedad ViewBag o ViewData que contiene SelectList o MultiSelectList con el mismo nombre que su modelo de propiedad que contiene los elementos seleccionados. Al menos no si está utilizando el ListBoxFor o DropDownListFor helper.
Aquí hay un ejemplo:
public class Person
{
public List<int> Cars { get; set; }
}
[HttpGet]
public ActionResult Create()
{
//wont work
ViewBag.Cars = new SelectList(carsList, "CarId", "Name");
//will work due to different name than the property.
ViewBag.CarsList = new SelectList(carsList, "CarId", "Name");
return View();
}
//View
@Html.ListBoxFor(model => model.Cars, ViewBag.CarsList as SelectList)
Estoy seguro de que hay muchas otras maneras de hacerlo, pero resolvió mi problema, ¡espero que ayude a alguien!
También me he quedado con este mismo problema y encontré el mismo problema con ListBox y ListBoxFor.
No importa lo que haga, no puedo hacer que las selecciones se realicen en ListBoxFor. Si cambio al ListBox y le pongo un nombre distinto al nombre de la propiedad de los datos a los que me estoy vinculando, se realizan selecciones.
Pero como no estoy usando ListBoxFor y los datos están dentro de una clase de modelo (Model.Departments) por ejemplo, no obtengo el enlace del modelo en el camino de regreso a mi controlador y, por lo tanto, la propiedad es nula.
EDITAR Encontré una solución publicada por otra persona aquí; Desafíos con la selección de valores en ListBoxFor