Gridview: Agrupar columnas en encabezado.

Cuando queremos que nuestro Gridview nos puede agrupar encabezado y que nos quede bien alineado a sus celdas correspondientes nos puede “doler” un poco esta tarea así que aquí un pequeño tip que espero sea de ayuda. A raíz de una pregunta en los grupos de noticias de ASP.NET dejo aquí los pasos a seguir con imágenes…

Mas abajo se encuentra para descargar el ejemplo

 

La idea…

Tenemos una tabla cuyo encabezado es así
image
Y queremos que nos quede asi
Agrupando y encima con dos filas …
image 

Utilizando CSS Friendly Adapter….

Antes cabe aclarar que estoy utilizando ASP.NET 2.0 CSS Friendly Control Adapters 1.0 
Por que?

Para que la tabla sea lo mas “amigable” a CSS y a Javascript (por si queremos tambien utilizar jQuery con ella) [+ info aqui]
Se renderiza…

Sin CSS Adapter Con CSS Adapter
image image

Es mucho pero que este ya que genera en cada celda (TR) contenido “sucio” pudiendo tranquilamente con estilos prevenirlo

No hay que hacer mucho trabajo para agregarlo a nuestro proyectos, simplemente descargar de CodePlex: http://www.codeplex.com/cssfriendly
Y luego mirar el ejemplo que es didáctico o te descargas el ejemplo al final de este articulo que estoy utilizando.

Algunos artículos en Geeks.ms sobre este componente:

 

 

Pasos a seguir para agrupar celdas en un encabezado (y no morir en el intento)

  1. Tenemos un grilla (con un listado de Jedis)
    image
    El encabezado
    image
     
  2. Empezamos con la primera aproximación, agrupando encabezado
    Queremos agrupar las tres primeras columnas y las dos ultimas.
    Para ello necesitamos el atributo colSpan de las celdas de una tabla, que aqui podremos obtenerlo en el evento RowDatabound del gridview
    Protected Sub GridView2_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView2.RowDataBound
           Select Case e.Row.RowType
               Case DataControlRowType.Header
    
                   'Agrupando las dos primeras columnas  (col=0, col=1 y col=2)
                   e.Row.Cells(0).ColumnSpan = 3
                   e.Row.Cells(1).Visible = False
                   e.Row.Cells(2).Visible = False
    
                   'Agrupando las dos ultimas columnas (col=3 y col=4)
                   e.Row.Cells(3).ColumnSpan = 2
                   e.Row.Cells(4).Visible = False
    
           End Select
       End Sub

    Y con esto nos queda agrupados

    Toma el texto de la primer columna del grupo ya que las demas no se renderizan

    image

    El HTML resultante de la parte del encabezado es:

    <thead>
        <tr>
            <th class="tipoImagen" colspan="3" scope="col">Imagen</th>
            <th colspan="2" scope="col">Especie</th>
        </tr>
    </thead>

  3. Ahora necesitamos un encabezado con dos filas

    Aqui podremos tener dos opciones para insertar una tabla en la celda agrupada, generando la tabla dinámicamente o insertándola

    • Opcion 1: Generando tabla dinámicamente

      Por ejemplo para el grupo 1

      'Agrupando las dos primeras columnas (col=0, col=1 y col=2)
        e.Row.Cells(0).ColumnSpan = 3
        e.Row.Cells(1).Visible = False
        e.Row.Cells(2).Visible = False
      
        'Opcion 1: Generando un tabla dinamicamente
        Dim tableCol1 As New HtmlTable
        Dim fila1, fila2 As New HtmlTableRow
        Dim celda11, celda21, celda22, celda23 As New HtmlTableCell
      
        'Creando la primer fila para el encabezado (a dos filas)
        'y agrupo por las cantidad de columnas hijas que tenga
        celda11.InnerText = "Datos Personales"
        celda11.ColSpan = 3
        fila1.Cells.Add(celda11)
      
        'Contenido a las celdas de la fila de abajo
        celda21.InnerText = "Imagen"
        celda22.InnerText = "Nombre"
        celda23.InnerText = "Fecha Nac."
      
        'Agregando celdas a las filas
        fila2.Cells.Add(celda21)
        fila2.Cells.Add(celda22)
        fila2.Cells.Add(celda23)
        tableCol1.Rows.Add(fila1)
        tableCol1.Rows.Add(fila2)
      
        'Formateando tabla
        tableCol1.Border = "0"
        tableCol1.CellPadding = "0"
        tableCol1.CellSpacing = "0"
      
        'Agregando una tabla generada dinamicamente a la celda 1 del encabezado 
        'que previamente la argupamos
        e.Row.Cells(0).Controls.Clear()
        e.Row.Cells(0).Controls.Add(tableCol1)

    • Opcion 2

      Aqui insertamos el html en crudo en la celda por código o hacemos una template para poder escribir el HeaderTemplate. Asi que depende de tu elección… 🙂

      • Opcion 2.1

        El código es muy “artesanal”

        'Agrupando las dos ultimas columnas (col=3 y col=4)
        e.Row.Cells(3).ColumnSpan = 2
        e.Row.Cells(4).Visible = False
        
        'Opcion 2: Agregando una tabla generada dinamicamente
        e.Row.Cells(3).Text = "<table border=0 cellpadding=0 cellspacing=0><tr><td colspan=2>Otros datos</td></tr><tr><td>Especie</td><td>GUID</td></tr></table>"

      • Opcion 2.2

        Creando una columna template para poder escribir en el HeaderTemplate

        <asp:TemplateField>
           <ItemTemplate>
               Contenido
           </ItemTemplate>
           <HeaderTemplate>
             <table border=0 cellpadding=0 cellspacing=0><tr><td colspan=2>Otros datos</td></tr><tr><td>Especie</td><td>GUID</td></tr></table>    
           </HeaderTemplate>
        </asp:TemplateField>

         
         
         
        El resultado de todo esto debería ser algo así:

        image

        Pero por tenemos un problema de alineación de estas celdas que están en una tabla en el encabezado (THEAD) con las celdas del cuerpo (TBODY) de nuestra tabla principal

        image

  4. Entonces el ultimo paso: Es Alinear las celdas del encabezado con las celda de datos mediante CSS

    Utilizando unos estilos “especiales” damos formato a estas celdas

    /* 
    -------------------------------------------------------------------
    TIPO DE COLUMNAS PARA JEDIS 🙂
    -------------------------------------------------------------------
    */
    /*COLUMNA: Imagen*/
    .YodaGrilla .AspNet-GridView table tbody tr td.tipoImagen
    {
        width:50px;
        max-width:50px;
        text-align:center;
    }
    /*  imagen dentro de la columna Imagen*/
    .YodaGrilla .AspNet-GridView table tbody tr td.tipoImagen img
    {
        width:50px;
        height:71px;
    }
    
    
    /*COLUMNA: Nombre*/
    .YodaGrilla .AspNet-GridView table tbody tr td.tipoNombre 
    {
        width:100px;
    }
    .YodaGrilla .AspNet-GridView table th .tipoNombre 
    {
        
    }
    /*COLUMNA: Fecha*/
    .YodaGrilla .AspNet-GridView table tbody tr td.tipoFecha
    {
        width:90px;
        text-align:center;
    }
    
    /*COLUMNA: Especie*/
    .YodaGrilla .AspNet-GridView table tbody tr td.tipoEspecie
    {
        width:120px;
        min-width:120px;
        text-align:center;
        /*background-color:Fuchsia;*/
    }
    
    /*COLUMNA: Guid*/
    .YodaGrilla .AspNet-GridView table tbody tr td.tipoGuid
    {
    
        text-align:center;
        /*background-color:Yellow;*/
    }

         
        El estilo hay que insertarlo tanto en las celdas del encabezado como en las celdas de datos

        En las celdas de datos

        <asp:GridView ID="GridView4" runat="server" AutoGenerateColumns="False" CssSelectorClass="YodaGrilla"
                DataSourceID="ObjectDataSource4">
                <Columns>
                     <asp:ImageField DataImageUrlField="ImagenURL" HeaderText="Imagen">
                        <ItemStyle  CssClass="tipoImagen" />
                        <HeaderStyle CssClass="" />
                    </asp:ImageField>
                    <asp:BoundField DataField="Nombre" HeaderText="Nombre" 
                        SortExpression="Nombre">
                        <ItemStyle CssClass="tipoNombre" />
                    </asp:BoundField>
                    <asp:BoundField DataField="FechaNacimiento" HeaderText="Fecha Nacimiento" 
                        SortExpression="FechaNacimiento">
                        <ItemStyle CssClass="tipoFecha" />
                    </asp:BoundField>
                    <asp:BoundField DataField="Especie" HeaderText="Especie" 
                        SortExpression="Especie">            
                        <ItemStyle CssClass="tipoEspecie" />
                        <HeaderStyle CssClass="" />
                    </asp:BoundField>         
                    <asp:BoundField DataField="Guid" HeaderText="Guid" SortExpression="Guid">            
                        <ItemStyle CssClass="tipoGuid" />
                    </asp:BoundField>           
                </Columns>
            </asp:GridView>


        Y en las celdas del encabezado…

        Ya sea en la tabla generada

        'Contenido a las celdas de la fila de abajo
        celda21.InnerText = "Imagen"
        celda21.Attributes.Add("class", "tipoImagen")
        celda22.InnerText = "Nombre"
        celda22.Attributes.Add("class", "tipoNombre")
        celda23.InnerText = "Fecha Nac."
        celda23.Attributes.Add("class", "tipoFecha")

        Y en la tabla insertada en crudo

        'Opcion 2: Agregando una tabla generada dinamicamente
        e.Row.Cells(3).Controls.Clear()
        e.Row.Cells(3).Text = "<table border=0 cellpadding=0 cellspacing=0><tr><td colspan=2>Otros datos</td></tr><tr><td class='tipoEspecie'>Especie</td><td class='tipoGuid'>GUID</td></tr></table>"

        Y alli…visualizaremos

        image

 

Ejemplo para la descarga

 

Si no funciona la incrustación de arriba click aqui

Enlaces

3 comentarios en “Gridview: Agrupar columnas en encabezado.”

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *