Llenar un DropDownList en una GridView

Hay una manera muy simple de llenar un combo, ya sea con los mismo valores o con distintos, en cada fila de una GridView en ASP.NET 2.0 (VS 2005). Lo primero que hay que hacer es (obviamente) dropear una gridview en la pagina y al insertar las columnas a la que queremos que sea nuestro combo la convertimos en Template de esta manera:

foto1.jpg

Hecho esto vamos a editar nuestro Template asi:
foto2.jpg

SIN USAR EDITITEMTEMPLATE

Dentro de ItemTemplate vamos a eliminar el Label que nos viene por defecto y dropear un DropDownList, no hace falta hacerlo en EditTemplate. Nos queda algo asi:
foto3.jpg

Al termina la edición nos queda algo asi:
foto4.jpg

Ahora nos pasamos a la parte HTML de la pagina para ver como nos queda la grilla:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" CellPadding="4"

           ForeColor="#333333" GridLines="None">

           <FooterStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />

           <Columns>

               <asp:BoundField DataField="nomCom" HeaderText="Nombre" />

               <asp:TemplateField HeaderText="Cargo">

                   <EditItemTemplate>

                       <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>

                   </EditItemTemplate>

                   <ItemTemplate>

                       <asp:DropDownList ID="DropDownList1" runat="server" Width="179px" DataTextField="CARGO" DataValueField="ID">

                       </asp:DropDownList>

                   </ItemTemplate>

               </asp:TemplateField>

           </Columns>

           <RowStyle BackColor="#EFF3FB" />

           <EditRowStyle BackColor="#2461BF" />

           <SelectedRowStyle BackColor="#D1DDF1" Font-Bold="True" ForeColor="#333333" />

           <PagerStyle BackColor="#2461BF" ForeColor="White" HorizontalAlign="Center" />

           <HeaderStyle BackColor="#507CD1" Font-Bold="True" ForeColor="White" />

           <AlternatingRowStyle BackColor="White" />

       </asp:GridView>

En mi caso todos los combos se llenan con la misma información por eso agrego el DataTextField ahí, esto se podría hacer del lado servidor.
Ahora lo mas importante del código esta en el evento RowDataBound de la grilla y es algo muy simple:

Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound        Try

            If e.Row.RowType = DataControlRowType.DataRow Then 'DataRow Vale las row que tienen datos, de esta manera se saltea el header,el footer y el pager

                Dim ddl As DropDownList

                Dim dt2 As DataTable = LlenarTabla2()

                'Celda 1 es donde esta el DropdownList

                Dim gvrow As GridViewRow = CType(e.Row.Cells(1).NamingContainer, GridViewRow)

                ddl = CType(gvrow.FindControl("DropDownList1"), DropDownList)

                ddl.ClearSelection()

If ddl IsNot DBNull.Value Then

                    ddl.DataSource = dt2

                    ddl.DataBind() 'Lleno el combo

                End If

                'Después de llenar el combo se puede asignar el valor si es que tenia uno

                'aca haciendo ddl.ddl.SelectedValue =...

            End If

        Catch ex As Exception

            Throw ex

        Finally

End Try

    End Sub

Al ejecutar el proyecto la pagina nos queda de esta manera.

foto5.jpg

Adjunto el proyecto aqui.

USANDO EDITITEMTEMPLATE

También se pueden usar las hermosas características que nos proporciona .NET 2.0 y usar la columna CommandField con los botones de Editar y Actualizar.

En este caso el HTML nos quedaría de esta manera:

<asp:GridView  ID="GridView2"  runat="server"

            OnRowCancelingEdit="GridView2_RowCancelingEdit"  OnRowEditing="GridView2_RowEditing"

            DataKeyNames="ID"  OnRowUpdating="GridView2_RowUpdating"  OnRowUpdated="GridView2_RowUpdated"

            ShowFooter="True"  CellPadding="4" ForeColor="#333333" GridLines="None" AutoGenerateColumns="False" >

        <Columns>

                <asp:BoundField DataField="nomCom" HeaderText="Nombre" />

                <asp:TemplateField HeaderText="Cargo">

                    <EditItemTemplate>

                        <asp:DropDownList ID="DropDownList1" runat="server" Width="179px" DataTextField="CARGO" DataValueField="ID">

                        </asp:DropDownList>

                    </EditItemTemplate>

                    <ItemTemplate>

                    <asp:Label ID="CargoText" runat="server" Text='<%# Eval("Cargo") %>'></asp:Label>

                    </ItemTemplate>

                </asp:TemplateField>

                <asp:CommandField ShowEditButton="True" EditText="Editar" />

            </Columns>

             <FooterStyle BackColor="#1C5E55" Font-Bold="True" ForeColor="White" />

             <RowStyle BackColor="#E3EAEB" />

             <EditRowStyle BackColor="#7C6F57" />

             <SelectedRowStyle BackColor="#C5BBAF" Font-Bold="True" ForeColor="#333333" />

             <PagerStyle BackColor="#666666" ForeColor="White" HorizontalAlign="Center" />

             <HeaderStyle BackColor="#1C5E55" Font-Bold="True" ForeColor="White" />

             <AlternatingRowStyle BackColor="White" />

    </asp:GridView>

La primer diferencia es que el Dropdownlist ahora está dentro de una Tag edititemtemplate, esto es porque el combo no va aparecer desde un principio con el ejemplo anterior sino que solo se va a renderear para la row que quiera editar. Y que se mostrará en su lugar? Buena pregunta, para eso está el ItemTemplate que muestra algo por defecto en todas las rows o como en mi caso el valor de “Cargo” (esto va a salir del datatable que llenará la grilla, le agrego un valor por defecto).

Ahora vamos al código en VB en este caso no solo voy a necesitar RowDataBound sino también el evento RowEditing (el que entrará en acción cuando el usuario de click a la row):

Partial Class _Default

    Inherits System.Web.UI.Page

    Dim dt1 As DataTable = LlenarTabla1()

    Dim ht As Hashtable

    Dim flag As Boolean = FalseProtected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        Try

            If Not Page.IsPostBack Then

                dBindData()

            End If

        Catch ex As Exception

            Throw ex

        End Try

    End Sub

Sub dBindData()

      GridView2.DataSource = dt1

      GridView2.DataBind()

End Sub

Protected Sub GridView2_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView2.RowDataBound

       Try

           If e.Row.RowType = DataControlRowType.DataRow Then 'DataRow Vale las row que tienen datos, de esta manera se saltea el header,el footer y el pager

               Dim ddl As DropDownList

               Dim dt2 As DataTable = LlenarTabla2()

               'Celda 1 es donde esta el DropdownList

               Dim gvrow As GridViewRow = CType(e.Row.Cells(1).NamingContainer, GridViewRow)

               ddl = CType(gvrow.FindControl("DropDownList1"), DropDownList)

If ddl IsNot Nothing Then

                   ddl.ClearSelection()

                   If ddl IsNot DBNull.Value Then

                       ddl.DataSource = dt2

                       ddl.DataBind() 'Lleno el combo

                   End If

                   If flag = True Then

                       'si no esta vacio la hashtable se lo asigno al combo

                       If Not String.IsNullOrEmpty(ht.Item(1)) Then ddl.SelectedValue = ddl.Items.FindByText(ht.Item(1)).Value

                   End If

               End If

End If

       Catch ex As Exception

           Throw ex

       Finally

End Try

   End Sub

Protected Sub GridView2_RowEditing(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewEditEventArgs) Handles GridView2.RowEditing

       Dim idIndex As Integer = e.NewEditIndex

       Try

           GridView2.EditIndex = idIndex

           Dim lblTexto As Label = GridView2.Rows(idIndex).Cells(1).FindControl("CargoText")

           Dim ddl As DropDownList = GridView2.Rows(idIndex).Cells(1).FindControl("DropDownList1")

           If lblTexto IsNot Nothing Then

               'Guardo un Hash con el valor que tiene el Label

               ht = New Hashtable

               'siempre en el value 1 porque lo voy a usar solo para un valor

               ht.Add(1, lblTexto.Text)

           End If

           'uso el flag para saber cuando esta rendereando 

           'el EditTemplate y no el Itemtemplate

           If ddl IsNot Nothing Then flag = True

           GridView2.DataSource = LlenarTabla1()

           GridView2.DataBind()

       Catch ex As Exception

           Throw ex

       Finally

End Try

End Sub

End Class

Uso una HashTable para almacenar el valor que voy a tener que setear en el DropDownList una vez seleccionado, sino siempre mostraría el 1er valor del Combo.

Dejo este 2do ejemplo para descargar aca

Saludos.

Anuncios

30 comentarios sobre “Llenar un DropDownList en una GridView

  1. ok me parece muy bien todo, me has sacado me muchas dudas, pero estoy tratando de adaptarlo dentro de un edittemplate y no encuentro como pasarles los dados a los dropdown al darle clic a editar

  2. Hola muy bueno el tutorial.
    Cómo se puede recibir el valor seleccionado? Tú has escrito lo siguiente:

    ‘Después de llenar el combo se puede asignar el valor si es que tenia uno

    ‘aca haciendo ddl.ddl.SelectedValue =…

    Cómo puedo recibir ese valor? Yo lo tengo guardado en un field llamado Status en la lista que llena el GridView.

  3. a ver si entendi bien, vos lo que podes hacer es usar ese ddl.selectedvalue que esta en el evento rowdatabound (que se ejecuta uno por cada fila) e ir poniendo el valor del status en el selectedValue, el SelectedValue es el valor de DataValueField por ejemplo un ID. Supongamos que tenes un datatable que es el que usas para bindear la grilla, en cada row de ese datatable vas a tener un status, entonces poder hacer datatable.select () para filtrar por la row en la que estas parado y ahi vas a hacer el ddl.selectedvalue =datatable(“status”).
    Avisame cualquier cosa, postea algo de codigo y lo vemos.
    Saludos

  4. Como cosigues el Selectvalue sigo sin entender.
    he estado investigando y en otros casos usan un control llamado
    <asp:controlParameter
    pero si me pueden resolver.
    esque en el ejemplo que estoy haciendo si llena los combos pero nose como extraerlos

  5. Hola.
    Soy nuevo en el uso del GridView y tengo una duda de tu codigo.
    Cuando creas el campo CARGO y lo conviertes a Combo, los datos de DataTextField=”CARGO” DataValueField=”ID” son del mismo datasource o son de otro. La pregunta es porque en mi caso, el combo se llena de un catalogo y los datos de las filas del grid son de una tabla. Asi que, cuales datos debo manejar para DataTextField y para DataValueField.
    Gracias

  6. Bueno a ver si entendi bien. Lo del Combo los Textfield y ValueField son los datos del Datasource. Por ejemplo si tu combo se llena por ejemplo con una Tabla que se tiene 2 columnas ID e Libro, esos 2 valores necesitas en el Combo. El combo se va llenar en todas las filas con el mismo origen. Entonces vos por un lado tenes las filas y por otro tenes el combo. El combo se llena siempre con lo mismo para todas las filas, fijate que yo hago:
    ddl.DataSource = dt2
    ddl.DataBind() ‘Lleno el combo
    donde dt2 es un datatable en tu caso seria tu origen de datos. El dt2 y los Textfield y ValueField del combo deben ser iguales.

    Saludos, espero que te haya ayudado.

    PD: ahora si. estoy logueado

  7. Hola de nuevo.
    Como le puedo hacer si en la primer columna del grid que es un combo, tengo que desplegar la descripcion del catalogo y en la segunda columna del grid tengo que desplegar una descripcion en ingles que esta en el mismo catalogo, ambos datos no vienen en el origen de datos del grid, unicamente su clave.
    Gracias

  8. El evento RowDataBound se va a parar en cada Row de tu grid, ahi es donde tenes que llenar el combo de la 1er columna con los datos que necesites.
    Dim gvrow As GridViewRow = CType(e.Row.Cells(1).NamingContainer, GridViewRow)
    ddl = CType(gvrow.FindControl(“DropDownList1″), DropDownList)

    Fijate que yo hago row.cells(1) esto es la 2da columna (porque empiezan en 0). Y ahí ddl vale el DropDownList que necesitas ponerle la descripción del catalago.

    Saludos, cualquier cosa pone algo de código y lo vemos.

  9. Hola, yo tnego un problema similar a Pepe. Lo que quiero saber es como obtengo el valor ID que me viene en la grilla para poder pasarlo al dropDownlist (ddl.selectedvalue = ? ). Yo estuve intentando algo así e.Row.DataItem(“cod”) pero no me funciona…

    Desde ya muchas gracias.

  10. Hola soy yo de nuevo.. jejej.

    Lo solucioné de la siguiente manera. Lo paso por si alguno le sirve.

    String idcod = null;

    idcod = Convert.ToString(DataBinder.Eval(e.Row.DataItem, “Idcod”));

    ddl.SelectedValue = idcod;

    suerte.

  11. Buen dia
    Necesito ayuda…. le asigne datos de SQL 2000 a un DataTable…. todo eso esta bien… pero necesito saber si el valor de la columna esta en Null (nothing) para asi realizar xxx accion…
    como lo hago en VB… estoy trabajando en ASP.NET 2.0 y VB..
    Gracias

  12. tengo un problema ..ya que tengo dos gridview rn una form web los dos contienen varios ddl el problem es que en el grid 1 se muestra la informacion sin problema, pero en el segundo todos los ddl muestran el primer valor…

    Podrias ayudarme??????????

  13. Otra forma de hacerlo mas simple:

    <!—->
    <asp:DropDownList ID=”selTrans” DataSource=”” DataTextField=”sNombre” DataValueField=”id” SelectedValue=”” Runat=server EnableViewState=False>

  14. Otra forma de hacerlo mas simple:

    <!—->
    <asp:DropDownList ID=”selTrans” DataSource=”” DataTextField=”sNombre” DataValueField=”id” SelectedValue=”
    ” Runat=server EnableViewState=False>
    Lo que esta entre son etiquetas de servidor y asi no necitamos usar el evento RowDataBound

  15. hola

    tengo un dropdownlist que lleno desde la bd, contiene la descripcion de una categoria, pero quisiera acceder a la clave de la categoria al seleccionar esa descripcion. como le puedo hacer?

    gracias.

  16. Que tal !.. Excelente articulo.. Hay alguna forma de que, en el row_Databound me genere 3 DDL, pero que el tercer DDl traiga datos dependiendo de lo que se eligio en los primeros dos??.. entiendo que al cambiar los dos primeros DDL se genera SelectedIndexChanged, pero como llenar el tercer combo dependiendo de lo que tengan los dos primeros? Gracias !!

  17. Disculpa la molestia,me he leido tu articulo y esta muy interesante y es muy bueno,excelente. Pero no se como hacer para llenar otro dropdownlist apartir del primero,osea que selecione un elemento y me haga una consulta filtrada por datavaluefield de mi primer drop,obviamente los dos dropdownlist estan en el datagrid.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s