Volviendo al tema de la programación (y después de mostrarles que no me gusta el fútbol) les he traído un ejemplo ya muy visto en PHP, pero muy poco utilizado en ASP.NET. Es un ejemplo sobre listas desplegables (o selects) dependientes, algo muy interesante y muy útil para formularios de registro, para eso utilizaremos los archivos del ejemplo de recursividad de este artículo, así como la tabla tm_ubigeo del artículo sobre el TreeView recursivo.
Para empezar, hay que saber que utilizaremos las extensiones AJAX que vienen por defecto en la versión 2008 de Microsoft Visual Studio, si usas la versión 2005 puedes descargar las extensiones desde aquí, pero tendrás que arreglártelas por si hay algún problema al momento de ejecutar el ejemplo. Si usas la versión 2010, bien por ti, si usas una más vieja que la 2005, entonces jódete.
Ahora bien, en la página web sobre la cual trabajaremos agregamos un control ScriptManager, y luego un control DropDownList, al cual llamaremos (o le pondremos de ID, para el caso es lo mismo) cboRegion:

Luego agregaremos a la página un control UpdatePanel, que nos ayudará a crear la funcionalidad AJAX de recarga de combos ¿o acaso creen que van a recargar todo el formulario sólo para recargar tres miserables combos?

Cómo ves en la imagen anterior, el control UpdatePanel puede contener cualquier tipo de control dentro de sí, así que le agregaremos otro control DropDownList al cual llamaremos cboProvincia, y repetiremos el mismo proceso para otro combo al cual llamaremos cboDistrito. Al final, la página tiene que quedar de esta forma:

Perfecto, ahora iremos a nuestra base de datos (cuyo código está en este artículo) y modificaremos el procedimiento pa_ubigeo_listar, de esta manera (el código original de este procedimiento está en este otro artículo:
Código:
alter procedure pa_ubigeo_listar
(
@tipo varchar(10),
@param1 int
)
as
begin
if @tipo = 'nodos'
begin
select tm_idubigeo, tm_nomubigeo, dbo.fc_Obtenervalorcomun('tm_tipoubigeo', tm_tipoubigeo) as tipoubigeo
from tm_ubigeo
where tm_idubigeosup = @param1
end
if @tipo = 'combos'
begin
create table #temp_ubigeo (tm_idubigeo int, tm_nomubigeo varchar(50), tm_idubigeosup int)
insert into #temp_ubigeo values (-1, 'Seleccione...', @param1)
insert into #temp_ubigeo
select tm_idubigeo, tm_nomubigeo, tm_idubigeosup from tm_ubigeo where tm_idubigeosup = @param1
select tm_idubigeo, tm_nomubigeo from #temp_ubigeo where tm_idubigeosup = @param1
drop table #temp_ubigeo
end
if @tipo = 'listado'
begin
select tm_idubigeo, replace(tm_nomubigeo, ' ', '—') as tm_nomubigeo,
dbo.fc_Obtenervalorcomun('tm_tipoubigeo', tm_tipoubigeo) as tipoubigeo
from fc_ubigeo(1)
end
end
Fíjense que cuando se cumple la condición de selección “combos”, estoy creando una tabla temporal para insertar de manera predeterminada la opción de “Seleccione…”, esto lo hago con la finalidad de que al momento de ejecutar la página, los cuadros desplegables informen al usuario de que seleccionen alguno de sus elementos.
Ahora regresamos a Visual Studio, y hacemos la respectiva programación en cliente (usaremos una función ya creada en el artículo anterior). Primero programaremos el método que hará el llenado de los cuadros desplegables:
Código:
clsConexion cn = new clsConexion();
private void llenarSelect(DropDownList combo, int idref)
{
DataSet dts = new DataSet();
cn.abrirconexion();
dts = cn.dtsUbigeoListar("combos", idref);
cn.cerrarconexion();
if (dts.Tables["consulta"].Rows.Count != 1)
{
combo.DataValueField = "tm_idubigeo";
combo.DataTextField = "tm_nomubigeo";
combo.DataSource = dts.Tables["consulta"];
combo.DataBind();
combo.Enabled = true;
}
else
combo.Enabled = false;
}
Ahora bien, programamos en el evento Load de la página lo siguiente:
Código:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
this.llenarSelect(this.cboRegion, 1);
this.cboProvincia.Items.Add("Seleccione...");
this.cboProvincia.Enabled = false;
this.cboDistrito.Items.Add("Seleccione...");
this.cboDistrito.Enabled = false;
}
}
Para evitar que el cuadro desplegable cboRegion vuelva a llenarse, lo hacemos bajo la condición de que no debe llenarse si hay una recarga (o envío de datos) del formulario. Si te das cuenta a la función llenarSelect le envío como primer parámetro el primer cuadro desplegable, para que su llenado sea ni bien cargue la página, e iniciando desde 1, por ser el id del registro padre de la tabla recursiva. Luego nada más cambiamos el estado de los combos, para evitar que el usuario haga click en ellos al no tener datos.
Ahora bien, paso a explicar algo que estaba a punto de olvidarme. Sé que algunos de ustedes aún no habrán trabajado esta parte, por lo que ruego no saltar éste paso. Si ya sabes cómo configurar el control UpdatePanel, bien por ti, si no, entonces presta atención.
Vayamos al primer UpdatePanel que agregamos, luego vayamos a su ficha Propiedades y buscamos la propiedad Triggers, a la cual le haremos click en el botón que tiene tres puntitos, inmediatamente nos saldrá un cuadro de diálogo:

En esa ventana hacemos click en el botón “Agregar”, se nos añadirá un miembro llamado AsyncPostBack, que no es más que el tipo de respuesta que tendremos del servidor, en nuestro caso una respuesta asíncrona (recuerda que esto es AJAX):

Ahora bien, vemos en las propiedades del AsyncPostBack una propiedad llamada Comportamiento, en el cual se define el control y el evento que ejecutarán una acción determinada a llevarse a cabo en el UpdatePanel, mejor dicho, aquí definimos el control que “disparará” alguna acción en dicho UpdatePanel. Para esto en ControlID seleccionamos el control cboRegion, y en EventName, seleccionamos el evento que corresponde, en este caso, SelectedIndexChanged.
Tiene que quedarte así, y luego haces click en “Aceptar”:

El paso anterior se repite con el UpdatePanel que contiene al DropDownList cboDistrito, pero en el ControlID seleccionamos a cboProvincia y el mismo evento que el anterior.
Hacemos esto porque al momento de seleccionar un ítem del primer cuadro desplegable, o mejor dicho, al seleccionar una región, se tendrán que cargar las provincias que corresponden a dicha región en el otro cuadro cboProvincia, y lo mismo para cargar cboDistrito, y todo esto de manera asíncrona, para evitar la tediosa recarga del formulario y conseguir recargar sólo los cuadros desplegables. Pero bien, ¿cómo logramos esto?, primero hay que programar en el evento SelectedIndexChanged del DropDownList cboRegion:
Código:
protected void cboRegion_SelectedIndexChanged(object sender, EventArgs e)
{
this.llenarSelect(this.cboProvincia, Convert.ToInt32(this.cboRegion.SelectedValue));
if (this.cboProvincia.Enabled == false)
this.cboDistrito.Enabled = false;
}
Con la función llenarSelect, cargamos el control cboProvincia y según la condición que tiene este método verificamos si el cboProvincia está habilitado (ya que si está habilitado significa que existen provincias que corresponden a la región que hemos seleccionado), en caso contrario deshabilitamos el cboDistrito.
Luego en el cuadro desplegable cboProvincia repetimos el procesos, pero esta vez sin condición e indicando la carga del cuadro cboDistrito:
Código:
protected void cboProvincia_SelectedIndexChanged(object sender, EventArgs e)
{
this.llenarSelect(this.cboDistrito, Convert.ToInt32(this.cboProvincia.SelectedValue));
}
Ahora lo único que nos queda es ejecutar la página y probar esta mierda:

Bueno, eso es todo, en el archivo descargable he puesto un ejemplo adicional, para que ustedes lo revisen y toda la cosa. Espero les sea de utilidad este ejemplo a los usuarios de ASP.NET y C#, y para los maricas que quieran el mismo ejemplo en PHP, no se preocupen que ya les alcanzaré uno, no se desesperen putas.
Loveless les desea una muerte violenta, y es que en verdad los odio.
lovelessisma@gmail.com

Descargar
Me gusta:
Sé el primero en decir que te gusta esta post.
Esta muy bueno el post !!!!! me salvo el día Gracias
Linux es mejor !!!!
La concha de tu madre.
DON FORGET ENABLE AUTOPOSTBACK IN THE FIRST COMBO
Al primer combo hay que agregarle la propiedad AUTOPOSTBACK =”true”.
Gracias por la intención de corregir, pero eso lo hice a drede, es obvio que para que funcione el primero tiene que funcionar bien.
No quería comentar sobre eso, pero habiendo dos comentarios sobre ello creo que había que alzar la voz para que otros usuarios no se confundan o piensen mal de uno.
Gracias está estupendo el post, lo implementé y me funciona de maravilla, pero hay un detalle, cuando intento utilizar estos combos dependientes en un control DetailsView me marca error:
Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.
JaJaJa me gusta eso de maricas de PHP la verdad le estoy tomando mas el gusto a .net Saludos