Documentos de Académico
Documentos de Profesional
Documentos de Cultura
NET
Burbujas en .NET
Pues… cosas mías sobre .NET y desarrollo web.
Para ilustrar las distintas opciones partimos de una clase “Database” que simula un contexto de ORM. Es una clase que sim-
plemente tiene dos listas (estáticas), una de ciudades (Cities) y otra de provincias (States). La definición de las clases City y
State son:
https://geeks.ms/etomas/2013/04/25/combos-en-asp-net-mvc/ 1/13
7/12/22, 9:14 Combos en ASP.NET MVC – Burbujas en .NET
{
public int Id { get; set; }
public string Name { get; set; }
}
1. SelectListItem
En HTML una combo (<select>) contiene una lista de opciones que siempre son clave y texto que se muestra (ambos alfanu-
méricos). Para representar esta información en ASP.NET MVC disponemos de la clase SelectListItem. SelectListItem nos per-
mite almacenar la clave (Value) y el texto (Text), así como un valor booleano (Selected) que indica si este es el elemento se-
leccionado por defecto a la combo (se corresponde al atributo selected del tag <option>).
Obtenemos las ciudades y luego convertimos cada objeto “City” en un objeto SelectListItem. Finalmente guardamos esta
lista de SelectListItem en el ViewBag.
@Html.DropDownList("Cities")
El nombre usado “Cities” es el nombre del campo usado en el ViewBag y donde se encuentra la lista de SelectListItem.
https://geeks.ms/etomas/2013/04/25/combos-en-asp-net-mvc/ 2/13
7/12/22, 9:14 Combos en ASP.NET MVC – Burbujas en .NET
La combo generada tendrá un atributo name llamado Cities y esto es importante a la hora de recibir el valor seleccionado
de la combo. Hay una gran confusión en esto. Una combo envia UN SOLO ELEMENTO al controlador: El ID del elemento
seleccionado.
[HttpPost]
public ActionResult Index(string Cities)
{
var id = Int32.Parse(Cities);
// Recuperamos la ciudad ==> Consulta a BBDD
var city = Database.Cities.FirstOrDefault(c => c.Id == id);
// Operamos con la ciudad
}
1. Lo que recibimos en Cities NO es la lista de ciudades. Es el valor de la propiedad Value del SelectListItem seleccionado
(en mi caso el ID de la ciudad seleccionada).
2. El nombre del parámetro (Cities) es el mismo que el nombre del campo del ViewBag (y el mismo que pusimos en la lla-
mada a Html.DropDownList).
2. IEnumerable
Tener que convertir siempre nuestros datos (en este caso una lista de ciudades) a una lista de SelectListItem es muy pesado.
Por suerte hay una clase SelectList que hace esto por nosotros. Basta con pasarle el IEnumerable que queremos, el nombre
de la propiedad que es la clave y el nombre de la propiedad que contiene el texto a mostrar.
Hasta ahora en la vista hemos usado Html.DropDownList pasándole tan solo una cadena (Cities). Esta cadena determina:
El nombre del atributo name del <select> generado. Que a su vez es el nombre del parámetro cuando recibimos los datos
El nombre del campo del ViewBag que tiene los elementos.
Si no queremos que estos dos valores sean iguales, podemos espcificarle a Html.DropDown donde está el
IEnumerable<SelectListItem> que contiene los datos de la combo. Así en la vista podríamos utilizar:
Con esto le estamos diciendo que nos genere un <select> cuyo atributo name valga “selectedCity” y que los datos están en
ViewBag.Cities.
Ahora cuando recibimos los datos debemos tener presente que el parámetro ya NO se llama Cities, si no selectedCity:
[HttpPost]
public ActionResult Index(string selectedCity)
{
var id = Int32.Parse(selectedCity);
// Recuperamos la ciudad ==> Consulta a BBDD
var city = Database.Cities.FirstOrDefault(c => c.Id == id);
// Operamos con la ciudad
}
https://geeks.ms/etomas/2013/04/25/combos-en-asp-net-mvc/ 4/13
7/12/22, 9:14 Combos en ASP.NET MVC – Burbujas en .NET
4. HtmlDropDownListFor
Este helper lía un poco porque tendemos a compararlo con el resto de helpers similares. Así, si yo hago
Html.TextboxFor(m=>m.Name) me va a generar un Textbox vinculado a la propiedad Name del ViewModel de la vista.
HtmlDropDownListFor también espera una propiedad del modelo pero NO es la propiedad que tiene los elementos, si no
donde dejará el valor del elemento seleccionado.
Mucha gente se confunde y se cree que la propiedad que pasamos a Html.DropDownListFor es la propiedad que contiene
los valores a mostrar. Imaginemos que tenemos el siguiente ViewModel:
https://geeks.ms/etomas/2013/04/25/combos-en-asp-net-mvc/ 5/13
7/12/22, 9:14 Combos en ASP.NET MVC – Burbujas en .NET
[HttpPost]
public ActionResult Index(ComboCitiesViewModel info)
{
var id = info.SelectedCity;
// Recuperamos la ciudad ==> Consulta a BBDD
var city = Database.Cities.FirstOrDefault(c => c.Id == id);
// Operamos con la ciudad
}
Y aquí es donde hay otro punto de confusión: en info NO VAS A RECIBIR la lista de ciudades. Es decir la propiedad Cities va
a ser null:
¿Y eso? Pues bueno, simple y llanamente nadie manda estos valores de vuelta para el controlador. La lista de ciudades NO
está en la petición POST que hace el navegador y por lo tanto el controlador no la recibe.
De hecho, podríamos modificar el parámetro ComboCitiesViewModel para que fuese un string llamado SelectedCity y fun-
cionaría igual.
5. Combos encadenadas
https://geeks.ms/etomas/2013/04/25/combos-en-asp-net-mvc/ 6/13
7/12/22, 9:14 Combos en ASP.NET MVC – Burbujas en .NET
Lo que vamos a ver es una implementación de combos encadenadas pero SIN ajax. Es decir, seleccionas provincia, envías la
petición y te aparecen las ciudades. En una web “actual” seguramente se haría via Ajax, pero hacerlo de la “manera anti-
gua” nos permitirá terminar de ver como funcionan las combos.
La acción Index que envía la página inicial la modificamos para que rellene States:
@model MvcCombos.Models.ComboCitiesViewModel
@using (Html.BeginForm()) {
<label for="Cities">Ciudad:</label>
@Html.DropDownListFor(m=>m.SelectedState, new SelectList(Model.States, "Id", "Name"))
https://geeks.ms/etomas/2013/04/25/combos-en-asp-net-mvc/ 7/13
7/12/22, 9:14 Combos en ASP.NET MVC – Burbujas en .NET
if (Model.SelectedState != 0)
{
@Html.DropDownListFor(m=>m.SelectedCity, new SelectList(Model.Cities, "Id", "Name"))
}
<input type="submit" value="enviar" />
}
Es importante entender lo que hacemos en la vista:
1. Si NO hay provincia seleccionada (Model.SelectedState vale 0) entonces mostramos la primera combo para seleccionar
estado.
2. Si hay estado seleccionado entonces generamos la combo para seleccionar la ciudad.
Nota: Este código tiene algunos problemas, como p.ej. que ocurre si el usuario selecciona una provincia,
envía el formulario, y cuando aparece de nuevo la vista con las dos combos modifica la provincia
seleccionada? En una aplicación real deberías, al menos, deshabilitar la combo de estados cuando ya
haya estado seleccionado.
Y finalmente ahora la acción que recibe los resultados debe gestionar que será llamada dos veces (una para seleccionar el
estado, la segunda con estado y ciudad):
[HttpPost]
public ActionResult Index(ComboCitiesViewModel info)
{
if (info.SelectedState != 0 && info.SelectedCity == 0)
{
info.States = Database.States;
info.Cities = Database.Cities.Where(c => c.StateId == info.SelectedState);
return View(info);
https://geeks.ms/etomas/2013/04/25/combos-en-asp-net-mvc/ 8/13
7/12/22, 9:14 Combos en ASP.NET MVC – Burbujas en .NET
}
var id = info.SelectedCity;
// Recuperamos la ciudad ==> Consulta a BBDD
var city = Database.Cities.FirstOrDefault(c => c.Id == id);
// Operamos con la ciudad
}
Fíjate en un par de cosas:
1. Debemos volver a cargar todos las provincias dentro del viewmodel. Si no cuando la vista intente renderizar la combo de
provincias dará error.
2. En las ciudades seleccionamos tan solo aquellas que son de la provincia que el usuario ha seleccionado.
Insisto, en una vista “real” la segunda vez no mostraríamos la combo de provincias, quizá mostraríamos el nombre de la
ciudad seleccionada. Veamos como podríamos hacerlo.
Añadimos la propiedad para guardar el nombre de la provincia seleccionada. Y en la vista usamos esta propiedad o
Html.DropDownList en función de si hay o no provincia seleccionada:
@model MvcCombos.Models.ComboCitiesViewModel
https://geeks.ms/etomas/2013/04/25/combos-en-asp-net-mvc/ 9/13
7/12/22, 9:14 Combos en ASP.NET MVC – Burbujas en .NET
@using (Html.BeginForm()) {
<label for="Cities">Ciudad:</label>
if (Model.SelectedState == 0)
{
@Html.DropDownListFor(m => m.SelectedState, new SelectList(Model.States, "Id", "Name"))
}
else
{
<text>Provincia @Model.SelectedStateName </text>
@Html.DropDownListFor(m=>m.SelectedCity, new SelectList(Model.Cities, "Id", "Name"))
}
<input type="submit" value="enviar" />
}
Finalmente en la acción que recibe los datos nos ahorramos de rellenar de nuevo las provincias (ya que la vista ya no las
usará la segunda vez) y ponemos el nombre de la provincia seleccionada (fíjate que hemos de ir a buscarlo a la BBDD ya
que solo tenemos el ID):
[HttpPost]
public ActionResult Index(ComboCitiesViewModel info)
{
if (info.SelectedState != 0 && info.SelectedCity == 0)
{
info.SelectedStateName = Database.States.Single(s => s.Id == info.SelectedState).Name;
info.Cities = Database.Cities.Where(c => c.StateId == info.SelectedState);
return View(info);
}
var id = info.SelectedCity;
// Recuperamos la ciudad ==> Consulta a BBDD
var city = Database.Cities.FirstOrDefault(c => c.Id == id);
https://geeks.ms/etomas/2013/04/25/combos-en-asp-net-mvc/ 10/13
7/12/22, 9:14 Combos en ASP.NET MVC – Burbujas en .NET
1. La primera vez la vista mostrará la combo de provincias y el controlador recibirá en SelectedState el id de la provincia
seleccionada.
2. La segunda vez la vista mostrará un texto con el nombre de la provincia y la combo de ciudades y el controlador recibirá
en SelectedCity el ID de la ciudad seleccionada. Esta segunda vez el controlador NO recibirá SelectedState ya que no se
envía. En nuestro caso no es necesario ya que lo podemos sacar de la ciudad. Si fuese necesario deberíamos usar un
campo Hidden.
Bueno… creo que esto más o menos es todo. ¡Espero que este post os ayude a resolver las dudas que podáis tener con las
combos en ASP.NET MVC!
¡Un saludo!
kiquenet
26 abril, 2013 a las 08:00
https://geeks.ms/etomas/2013/04/25/combos-en-asp-net-mvc/ 11/13
7/12/22, 9:14 Combos en ASP.NET MVC – Burbujas en .NET
sebastianherrera
2 mayo, 2013 a las 17:52
Eduard, este caso muestra el ejemplo de dos tablas, una para estado y otra para city.
que cambiara en el caso de que sea un combo multiple para una sola tabla?. ejemplo tipico es la tabla categorias con multi-
ples parent id.
ejemplo:
categoryid | nombre de categoria | parent_categoryid
existe forma de hacer un multiples combos en funcion de la cantidad de parent categories que tenga?
muchas gracias!
sebastian.
etomas
8 mayo, 2013 a las 16:45
Buenas @sebastianherrera
ASP.NET MVC no soporta directamente el concepto de «combo múltiple para una sola tabla». Es decir, tu debes leer los datos
de esa tabla y organizarla en dos combos: dos objectos SelectList que mandas hacia la vista.
Saludos!
anonymous
12 noviembre, 2013 a las 14:54
https://geeks.ms/etomas/2013/04/25/combos-en-asp-net-mvc/ 12/13
7/12/22, 9:14 Combos en ASP.NET MVC – Burbujas en .NET
Buenas! Este post es para describir un fallo que he encontrado en el helper Html.DropDownFor y el workaround
https://geeks.ms/etomas/2013/04/25/combos-en-asp-net-mvc/ 13/13