Como Crear Barras de Desplazamiento en un DataGrid con el Net 2003

En este artículo describiré una manera sencilla de colocarle barras de desplazamiento Horizontales y Verticales a un DataGrid dejando fija la cabecera.



Ver ejemplo

Me he encontrado con un sin fin de artículos que te explican como colocar barras dedesplazamiento verticales a un datagrid, dejando fija la cabecera, cada uno explicando como hacerlo de diferente forma; algunos pintan una tabla sobre el datagrid, otros colocan dos datagrids, uno sobre otro, etc., etc., etc.

Estos ejemplos funcionaron bien para mí por un muy buen rato, mientras solo tuve que usar barras de desplazamiento verticales. El problema comenzó cuando en uno de los proyectos en los que participaba, se tenía que mostrar un datagrid con más de 6000 registros y 32 columnas; siendo mas que obvia la necesidad de barras de desplazamiento horizontales y verticales.

Fue bastante simple(pero laborioso) dibujar mi tablita html con el titulo de las 32 columnas, encerrar el datagrid entre etiquetas <div> con un ancho y un largo especifico y su etiqueta de estilo overflow: auto. Y listo tenia un datagrid con barras de desplazamiento, la vertical funcionaba muy bien, pero la horizontal... movía los datos y la cabecera.

La Solución:

Tras varias infructuosas horas de probar los escasos ejemplos que encontré y que mostraban como hacer funcionar la barra de desplazamiento horizontal encontré una solución bastante viable. Un artículo de Brett Merkey que muestra como por medio de una hoja de estilo, congelar la cabecera de una tabla HTML.

El truco esta en lograr que una tabla html encierre la cabecera entre etiquetas <thead> y <th> en lugar de <td> y el cuerpo entre etiquetas <tbody> para poder aplicarle después una hoja de estilo que bloquea la cabecera; y dado que un DataGrid cuando se dibuja en la respuesta de una pagina aspx, es una tabla html, tenemos gran parte de la tarea hecha. El problema ahora es ¿como lograr que el render de un datagrid se dibuje con estas etiquetas en lugar de con las típicas?

Tras muchas otras horas de investigación, muchas otras tasas de café y navegación en la documentación de Microsoft, encontré que Instalando el Service Pack para el Microsoft .NET Framework 1.1 se agregan unas cuantas nuevas propiedades al control DataGrid pero la que a nosotros nos interesa es UseAccessibleHeader la cual, cuando se establece en true permite que cuando el control DataGrid se dibuje, lo haga con etiquetas <thead>, <th> y <tbody>
Así que a Instalar el Service Pack para el Microsoft .NET Framework 1.1.
Listo, problema resuelto ahora, al código:

La hoja de estilo:

Una hoja de estilo, es un archivo de texto con extensión .css en el cual se define la forma en la que se verán algunos, uno o todos los elementos de una pagina web, este archivo puede aplicarse a todas las páginas web de un sitio. Para mayor información sobre hojas de estilo recomiendo el siguiente Manual de CSS

El siguiente código se copia en un archivo de texto con extensión .css, y se guarda en el subdirectorio donde se encuentra la aplicación web. En este ejemplo el archivo se llama locked-column.css y esta guardado dentro del subdirectorio css.

* Nota: el ejemplo de esta hoja de estilo fue tomado de la página de Brett Merkey

/*DIV que contendrá al DataGrid y muestra las barras de desplazamiento*/
div#div-datagrid {
width: 807px;
height: 200px;
overflow: auto;
scrollbar-base-color:#EEEEEE;
}

/*Bloquea la cabecera para que siempre se muestre*/
th {
font-size: 14px;
font-weight: bold;
text-align: center;
background-color: navy;
color: white;
border-right: 1px solid silver;
position:relative;
cursor: default;
top: expression(document.getElementById("div-datagrid").scrollTop-2); /*IE5+ only*/
 z-index: 10;
}

Una vez creada la hoja de estilo, lo que tenemos que hacer es, en nuestra pagina aspx, donde tenemos el datagrid, definir el archivo de estilos que vamos a utilizar, esto se logra añadiendo la siguiente línea dentro de las etiquetas <head> y </head> en el modo de Diseño;


<link href="./css/locked-column.css" type="text/css" rel="stylesheet">

donde ./css/ es el subdirectorio donde guardaste el archivo.

El envoltorio <DIV>

El siguiente paso es encerrar el DataSet entre etiquetas <div>; en este punto es muy importante observar, que cualquier div que valla a ser utilizado para bloquear la cabecera debe de asignarsele un Id, con el mismo Id que se definió en la hoja de estilo, o sea div-datagrid.


<DIV id="div-datagrid">
<asp:datagrid id="grdComp" runat="server" Width="1550px" Height="143px" AllowPaging="True" UseAccessibleHeader="True"
BackColor="White" BorderStyle="None" HorizontalAlign="Justify" PageSize="200" BorderWidth="1px"
CellPadding="3" GridLines="Vertical" BorderColor="#999999" AutoGenerateColumns="False">
<FooterStyle ForeColor="Black" BackColor="#CCCCCC"></FooterStyle>
<SelectedItemStyle Font-Bold="True" ForeColor="White" BackColor="#008A8C"></SelectedItemStyle>
<AlternatingItemStyle BackColor="Gainsboro"></AlternatingItemStyle>
<ItemStyle ForeColor="Black" BackColor="#EEEEEE"></ItemStyle>
<HeaderStyle Font-Bold="True" HorizontalAlign="Center" ForeColor="White" VerticalAlign="Top"
BackColor="#000084"></HeaderStyle>
<Columns>
<asp:BoundColumn DataField="A" HeaderText="Process"></asp:BoundColumn>
<asp:BoundColumn DataField="B" HeaderText="Supplier"></asp:BoundColumn>
<asp:BoundColumn DataField="C" HeaderText="Month"></asp:BoundColumn>
<asp:BoundColumn DataField="D" HeaderText="Order"></asp:BoundColumn>
<asp:BoundColumn DataField="E" HeaderText="Factor"></asp:BoundColumn>
</Columns>
<PagerStyle VerticalAlign="Top" HorizontalAlign="Left" ForeColor="Black" BackColor="#999999"
Mode="NumericPages"></PagerStyle>
</asp:datagrid>
</DIV>

Y por ultimo en la página de propiedades del DataGrid, establecemos la propiedad UseAccessibleHeader = true


también la ponemos en código dentro de la función Page_Load

private void Page_Load(object sender, System.EventArgs e){

if(!IsPostBack)
grdComp.UseAccessibleHeader = true;
}

Y listo, tenemos un datagrid con scroolbars en ambos sentidos.

Ver ejemplo

2 comentarios:

Anónimo dijo...

Otra forma para que sea soportado en cualquier navegador, es que en la hoja de estilo se coloque lo siguiente:

.freezeColumn {
background-color: white; position:relative; top:expression(this.offsetParent.scrollTop);
}

Pedro Chacón dijo...

Hola, estoy intentando utilizar los estilos para las barras, pero no se aplican cuando tengo el DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd", viendo como tu lo tienes, al quitarle la referencia al dtd funciona, pero me deja de funcionar un metodo que llamo en el evento onresize, que puedo hacer para que los dos funcionen.