Scroll completo para la grilla de ASP.NET


Introducción

Realmente el control del servidor DataGrid que provee el Visual Studio para ASP.NET es muy fácil y cómodo de usar.  Con simplemente establecer un par de propiedades podemos generar un tag <table> con todos sus <tr> y sus <td> a partir de una fuente de datos. Recuerden el trabajo que debíamos tomarnos anteriormente, abrir un recordset, recorrerlo en un bucle y ejecutar Response.Write de cada uno de los tags. Ahora con un simple arrastrar y soltar sobre la página aspx tenemos una tabla con la posibilidad de ordenamiento, paginado, filtrado, edición, etc.


Sin embargo, si decidimos no usar la paginación para evitarnos los round-trips, y la cantidad de registros es considerable, haremos que el usuario necesite desplazar la página para ver la totalidad de los registros.  Esto es contraproducente, ya que el usuario pierde la referencia de la cabecera de la tabla, o podría dejar de ver cierta información relevante como ser un menú ubicado al principio de la página.


Lo ideal es poder darle a la grilla las típicas barras de desplazamiento (scroll) que toda grilla de Windows Forms posee.


Veremos paso a paso la evolución que lleva al resultado final.


Solución


Para agregar barras de scroll, debemos encerrar la grilla en un tag <DIV>, especificar el tamaño de la caja y establecer la propiedad Overflow = auto de CSS (hojas de estilo en cascada), la cual añadirá las barras horizontal y/o vertical según sean necesarias.

<div style=”overflow:auto; width:400px; height:201px” >
    <asp:datagrid id=“DataGridFilas” runat=”server” DataSource=”<%# dataSet11 %>“></asp:datagrid>
<
div/>

El resultado obtenido es el siguiente



A simple vista parece que hemos encontrado la solución, pero no…  Si el usuario desplaza la barra vertical, inmediatamente perderá la referencia a la cabecera de la grilla, como muestra la siguiente figura.



Lo que propongo entonces, es separar la cabecera de las filas usando 2 grillas.  La grilla de la cabecera, DataGridCabecera, estará contenida por un <div> del mismo tamaño de la grilla inferior y tendrá ocultas las barras de desplazamiento.  Dejando habilitadas las barras de desplazamiento para la grilla que contiene las filas solamente, DataGridFilas,

<div style=”overflow: hidden; width: 400px”>
   
<asp:datagrid id=“DataGridCabecera” runat=”server” DataSource=”<%# dataSet11 %>“></asp:datagrid>
</
div>
<div style=”overflow: auto; width: 400px; height: 201px” >
   
<asp:datagrid id=“DataGridFilas” runat=”server” DataSource=”<%# dataSet11 %>“></asp:datagrid>
<
div/>

Debemos definir un ancho fijo para las columnas de ambas grillas, ya que generaremos 2 tags <table> distintos.

<div style=”overflow: hidden; width: 400px”>
    <
asp:datagrid id=“DataGridCabecera” runat=”server” DataSource=”<%# dataSet11 %>“>
       
<Columns>
            <
asp:BoundColumn DataField=”ProductID” SortExpression=”ProductID” HeaderText
=”ProductID”>
               
<HeaderStyle Width=”80px”></HeaderStyle
>
           
</asp:BoundColumn
>
           
<asp:BoundColumn DataField=”ProductName” SortExpression=”ProductName” HeaderText
=”ProductName”>
               
<HeaderStyle Width=”250px”></HeaderStyle
>
           
</asp:BoundColumn
>
              
….
        
</Columns
>
    </
asp:datagrid>
</
div>

<div style=”overflow: auto; width: 400px; height: 201px” >
     <
asp:datagrid id=“DataGridFilas” runat=”server” DataSource=”<%# dataSet11 %>“>
         
<Columns>
               <
asp:BoundColumn DataField=”ProductID” SortExpression=”ProductID” HeaderText
=”ProductID”>
                  
<HeaderStyle Width=”80px”></HeaderStyle
>
              
</asp:BoundColumn
>
              
<asp:BoundColumn DataField=”ProductName” SortExpression=”ProductName” HeaderText
=”ProductName”>
                  
<HeaderStyle Width=”250px”></HeaderStyle
>
               
</asp:BoundColumn
>
              
….
         
</Columns
>
    </
asp:datagrid>
<
div/>


La grilla original DataGridFilas, debe ocultar la cabecera para no mostrarse 2 veces; para ello crearemos una clase de CSS llamada Esconder, que reduce el tamaño al 1%.

<STYLE>
   
.Esconder {zoom=1%;}
</STYLE>

Y se la aplicaremos al HeaderStyle de la grilla:

<div style=”overflow: hidden; width: 400px”>
    <
asp:datagrid id=“DataGridCabecera” runat=”server” DataSource=”<%# dataSet11 %>“>
       
<Columns>
            <
asp:BoundColumn DataField=”ProductID” SortExpression=”ProductID” HeaderText=”ProductID”>
               
<HeaderStyle Width=”80px”></HeaderStyle>
           
</asp:BoundColumn>
           
<asp:BoundColumn DataField=”ProductName” SortExpression=”ProductName” HeaderText=”ProductName”>
               
<HeaderStyle Width=”250px”></HeaderStyle>
           
</asp:BoundColumn>
              
….
        
</Columns>
    </
asp:datagrid>
</
div>

<div style=”overflow: auto; width: 400px; height: 201px” >
     <
asp:datagrid id=“DataGridFilas” runat=”server” DataSource=”<%# dataSet11 %>“>
         <HeaderStyle CssClass=”Esconder”></HeaderStyle>
         
<Columns>
               <
asp:BoundColumn DataField=”ProductID” SortExpression=”ProductID” HeaderText=”ProductID”>
                  
<HeaderStyle Width=”80px”></HeaderStyle>
              
</asp:BoundColumn>
              
<asp:BoundColumn DataField=”ProductName” SortExpression=”ProductName” HeaderText=”ProductName”>
                  
<HeaderStyle Width=”250px”></HeaderStyle>
               
</asp:BoundColumn>
              
….
         
</Columns>
    </
asp:datagrid>
<
div/>


La nueva grilla DataGridCabecera que muestra la cabecera no se vinculará a la fuente de datos, de forma tal de no crear las filas que muestran los registros. Este es el código asociado a la carga de la página.  Las 2 grillas están asociadas al dataSet11, sin embargo solo DataGridFilas mostraré las filas ya que el DataSet no esta caragado aún cuando DataGridCabecera.DataBind() es ejecutado.


private void Page_Load(object sender, System.EventArgs e)
{
    DataGridCabecera.DataBind();
    sqlDataAdapter1.Fill(dataSet11);
    DataGridFilas.DataBind();
}


Este es el resultado obtenido:



¿Qué pasa, si el usuario mueve la barra de deslizamiento horizontal?  Se moverán las filas lateralmente y quedará fija la cabecera. ¡Que feo!.



Completemos la solución: lo que necesitamos es poder desplazar la cabecera, DataGridCabecera, tantos píxeles como la barra de desplazamiento que contiene a la grilla DataGridFilas se deslice.


En el evento onscroll del <div> que muestra las barras de desplazamiento, agregaremos código Javascript para sincronizar el movimiento lateral de las filas con la cabecera, de forma tal de mover la cabecera tantos píxeles como lo haga la barra de desplazamiento horizontal. Es necesario entonces que la grilla cabecera DataGridCabecera tenga una posición relativa al <div> que la contiene para poder moverla: style=”position: relative”.


<STYLE>
   
.Esconder {zoom=1%;}
</STYLE>


<script language=”JScript”>
   
function DoScroll()
    {
        document.all(
“DataGridCabecera”).style.pixelLeft = divScroll.scrollLeft * -1;
    }
</script>

<div style=”overflow: hidden; width: 400px”>
    <
asp:datagrid id=“DataGridCabecera” runat=”server” style=”position:relative” DataSource=”<%# dataSet11 %>“>
       
<Columns>
            <
asp:BoundColumn DataField=”ProductID” SortExpression=”ProductID” HeaderText=”ProductID”>
               
<HeaderStyle Width=”80px”></HeaderStyle>
           
</asp:BoundColumn>
           
<asp:BoundColumn DataField=”ProductName” SortExpression=”ProductName” HeaderText=”ProductName”>
               
<HeaderStyle Width=”250px”></HeaderStyle>
           
</asp:BoundColumn>
              
….
        
</Columns>
    </
asp:datagrid>
</
div>
<div style=”overflow: auto; width: 400px; height: 201px” id=”divScroll” onscroll=”DoScroll()”>
     <
asp:datagrid id=“DataGridFilas” runat=”server” DataSource=”<%# dataSet11 %>“>
         <HeaderStyle CssClass=”Esconder”></HeaderStyle>
         
<Columns>
               <
asp:BoundColumn DataField=”ProductID” SortExpression=”ProductID” HeaderText=”ProductID”>
                  
<HeaderStyle Width=”80px”></HeaderStyle>
              
</asp:BoundColumn>
              
<asp:BoundColumn DataField=”ProductName” SortExpression=”ProductName” HeaderText=”ProductName”>
                  
<HeaderStyle Width=”250px”></HeaderStyle>
               
</asp:BoundColumn>
              
….
         
</Columns>
    </
asp:datagrid>
<
div/>

De esta forma tendremos una grilla con la funcionalidad de desplazamiento idéntica a un control Windows Forms.



Descargar codigo completo


Conclusión


El uso de herramientas como CSS (Hojas de estilo en cascada) y DHTML son perfectamente factibles de combinar con los nuevos elementos que introduce ASP.NET permitiéndonos crear interfaces de usuario mas amigables.


Este artículo fue publicado originalmente en la revista MTJ.NET de MSDN Latinoamérica en Diciembre del 2003

digg_url = ‘http://msmvps.com/blogs/cwalzer’;
digg_bgcolor = ‘#ff9900’;
digg_skin = ‘compact’;
digg_window = ‘new’;

Agregar a Technorati

17 thoughts on “Scroll completo para la grilla de ASP.NET

  1. y el ordenamiento por columnas la paginacion…se pieerde todo eso …una cosa por otra…la idea de usar dos grillas no me gusta…ademas esta solucion al ingresarle palabras de 200 caracteres sin espacios las celdas se descuadran

    SAludos

  2. Mas alla de la primera critica , me gusta la idea de dos grillas..qizas coincido que las celdas de descuadrarian cuando se ponen mas caracteres de lo esperado….

    Pero creo muy importante y valioso que la gente suba estos tutoriales…

    Gente como vos se merece respeto!!

    Saludos!!

  3. Vaya… que pedante el primer tipo, si no te interesa simplemente no hubieras dejado comentarios.
    Gracias por el aporte, ocupaba lo que nos proporcionaste.

  4. hola..aplique los que explicas en un gridview pero tengo un problema, si al gridview del emcabezado le pongo style =”position :relative” no respeta las medidas del div mostrando todos los datos, pero si le quito, el desplazamiento horizontal es solo para el detalle y no toma en cuenta el encabezado.
    si alguien sabe como hacerlo, le agradeceria mucho me diga como

  5. Como lo hago en visual studio 2008 VS.net ???
    tengo problemas para colocarlo.
    no se si sera porque ocupo ajax(UpdatePanel) y paneles …

  6. Con esto que aportas complementaste una idea que ya tenia, gracias y saludos…
    Sabes de alguna palabra de 200 caracteres, jajaj

  7. buuuuuuu quien me ayuda la solución está buena pero como dice el 1 tipo yo también ordeno en las cabeceras así q esta solución no me sirve, todas las soluciones q he visto funcionan en IE7 pero yo quiero en IE9, necesito fijar mis cabeceras q ordenen y q no se queden pegadas cuando navego de panel en panel con update…por favor ayudenmeeeee 🙁

Leave a Reply

Your email address will not be published. Required fields are marked *