Cómo colocar un icono para indicar la ordenación en la cabecera de un GridView

Esta pregunta surge muchas veces en cursos y conversaciones técnicas varias. La cosa es la siguiente: tengo una rejilla (GridView) de ASP.NEt 2.0 en un formulario ASPX, y he activado las opciones de ordenar sus columnas, de modo que cuando pulso sobre una cabecera logro de manera automática la ordenación por el campo correspondiente. Es estupendo pues no tengo ni que escribir código para lograrlo, al contrario de lo que pasaba al usar un DataGrid en ASP.NET 1.x.


Pero… ¿Qué pasa si quiero evidenciar de un modo más claro cuál es el orden concreto de mi rejilla?


Lo típico es colocar un iconito con una flecha hacia arriba o hacia abajo en la cabecera adecuada para indicarlo, algo así:




(Fíjate en el iconito al lado de «Nombre» que indica el orden inverso)


Pero ¿cómo lo consigo?


Hay que responder adecuadamente al evento RowCreated de la rejilla.


Antes de nada asegúrate de tener un par de iconos para las flechas de ordenación. En mi caso los he colocado en la carpeta «Imgs» de la raíz de mi aplicaicón y les he llamado sort_asc.gif y sort_desc.gif.


Ahora en tu rejilla responde al evento RowCreated de la siguiente manera (en C#):


protected void GridView1_RowCreated(object sender, GridViewRowEventArgs e)
{
  GridView grd = (GridView)sender;

  if (e.Row.RowType == DataControlRowType.Header)
  {
    foreach (TableCell tc in e.Row.Cells)
    {
      if (tc.HasControls())
        {
          // Buscar el enlace de la cabecera
          LinkButton lnk = tc.Controls[0] as LinkButton;
          if (lnk != null && grd.SortExpression == lnk.CommandArgument)
            {
              // Verificar que se está ordenando por el campo indicado en el comando de ordenación
              // Crear una imagen
              System.Web.UI.WebControls.Image img = new System.Web.UI.WebControls.Image();
              // Ajustar dinámicamente el icono adecuado
              img.ImageUrl = «~/imgs/sort_» + (grd.SortDirection == SortDirection.Ascending ? «asc» : «desc») + «.gif»;
              img.ImageAlign = ImageAlign.AbsMiddle;
              // Le metemos un espacio delante de la imagen para que no se pegue al enlace
              tc.Controls.Add(new LiteralControl(» «));
              tc.Controls.Add(img);
            }
         }
       }
     }
   }


Veamos lo que se hace:


Primero se convierte el argumento genérico sender en una referencia a una rejilla. De este modo obtenemos una referencia a la rejilla que ha lanzado el evento y el mismo método nos puede servir para colocar el icono en todas las rejillas de la misma página (por supuesto podemos ir un poco más allá y colocar este manejador en un módulo en App_Code y reutilizarlo para toda la aplicación).


Acto seguido comprobamos si el elemento que se está creando es una cabecera de la rejilla o no puesto que este evento se lanza para todas las filas de la misma, y sólo nos interesan en este caso las cabeceras.


Una vez que estamos seguros de estar trabajando con la fila de la cabecera recorremos todas sus celdas en busca de controles de tipo LinkButton. Sólo las celdas de la cabecera de campos por los que está permitido ordenar tienen un control de este tipo (sobre el que pulsamos para conseguirlo). Las demás tienen simples etiquetas Label. Es decir, si hay un LinkButton es que esa celda permite ordenación. Además dicho control estará de primero (y único) en la celda.


Por lo tanto sólo nos resta comprobar si además de permitir la ordenación estamos en la celda concreta, es decir, en la celda por la que se está ordenando actualmente la rejilla. ¿Cómo lo sabemos?


Cuando la rejilla se ordena se establece automáticamente su propiedad SortExpression con el nombre del campo de la columna por la cual estamos ordenando. Éste nombre se obtiene precisamente de la propiedad CommandName del enlace de la cabecera correspondiente. Por lo tanto si el comando asociado con el enlace que estamos comprobando coincide con el campo de ordenación actual de la rejilla, ¡esta es nuestra cabecera!.


Por fin, si estamos en la cabecera correcta sólo tenemos que introducir la imagen, que es justo lo que se hace en el último trozo de código y que está explicado con comentarios: se crea una imagen, se le asocia el icono correspondiente a la dirección de ordenación y se añade al final de la celda actual con un espacio por el medio para separarlo del enlace.


¡Listo!


Espero que te resulte útil.

Sin categoría

8 thoughts on “Cómo colocar un icono para indicar la ordenación en la cabecera de un GridView

  1. ¿Y sí en vez de comprobar que sea un link button, no comprobamos que el Row contenedor del Cell sea un Rowheader? (creo que se llama así)

    Tambien sería buena idea no?, ya que al hacerlo con los linkbutton, quizá este código se ejecute en cualquier cell que contenga un linkbutton, y no tiene porque ser solo la de la cabecera.

    Muy buena la explicación, saludos.

  2. Sergio:

    Si conviertes alguna columna en una plantilla y modificas la generación automática de la cabecera, entonces tendrás que tratarla de manera especial, claro.

    Neu:

    Si te fijas la primera comprobación que se hace es precisamente la de que sea una fila de cabecera para evitar que pase eso que comentas:

    if (e.Row.RowType == DataControlRowType.Header)

    de este modo sólo se procesan efectivamente las cabeceras.

    Saludos

    JM.

  3. Ah… me ahorraste el trabajo de probar :D. Entonces pasa lo mismo cuando usas un select personalizado, con un templateField.

    Gracias :D!

    Saludos,

  4. Necesito saber urgentemente como ordenar letras en un jcomboBox.Atraves de un Jbutton, que al adarle clic al jbutton aparezca ordenado una palabra en el jcombobox

Deja un comentario

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