Hoy truco rápido
La verdad que entiendo a los escritores cuando dicen que están bloqueados y que no saben de que escribir. Este mes me ha costado mucho encontrar un tema del que hablar, ya que como sabéis, este blog principalmente se alimenta de problemas, o desafíalos a los que me he enfrentado, pero si no me pasa nada "raro" durante el mes, claro, ¿de que hablo entonces? Bueno pues hoy al final, no es que haya sido algo muy "raro", pero es algo que más o menos necesitamos hacer con mucha frecuencia, y es que en WinForms tras la carga de un DataGridView necesitamos que se seleccione la última fila de la lista.
En sí, no es difícil de hacer, pero son varias líneas de código una y otra vez. Es por ello que se me ocurrió hacer un método de extensión y así no tener que estar escribiendo siempre los mismo. Hay que seguir los principios de programación e intentar hacer un código lo más "profesional" posible desde el primer minuto, incluso si eres el único programador o si tu aplicación solo la vas a usar tu o en tu empresa.
Paso uno. Analizar que es lo que vamos a "minimizar"
Para empezar quería aclarar realmente qué es lo que vamos a "minimizar" con este truco. Por lo que vamos a ver que líneas de código necesitamos para poder seleccionar la última fila dentro de DataGridView cuando, por ejemplo, lo rellenamos, o desde un botón de accion en plan, primero y último. Ya que para seleccionar el primero sería básicamente lo mismo, pero siemrpe del ínidice 0 de las los Rows.
void SelectLastRow(){
//limpiar seleccion actual
dataGrid.ClearSelelection();
//obtener última fila
int lastRowsIndex = dataGrid.Rows.Count - 1;
//seleccinar la fila complete
dataGrid.Rows[lastRowsIndex].Selected = true;
//posicionar el cursor en la primera celda
dataGrid.CurrentCell = dataGrid.Rows[lastRowsIndex].Cells[0]; //ojo la celda debe de esta visible
//repintar el grid para que se vea la fila seleccinada
//en la posicion del la celda seleecionada
dataGrid.Refresh();
}
Como puesdes comprobar con muchas líneas, para tener que estar escribiendo cada vez que queramos hacer esta acción dentro de un formulario, inclusi aunque lo metamos entro de un método como he representado en este caso.
Normalmente haríamos un método parecido a éste para cada uno de los grids que tuvieramos en cada form. Ahí es dónde con un método de extensión ya podríamos empezar a ahorrar líneas de código.
Paso dos. Refactorizar para crear un método de extensión
Bueno, como sabéis los métodos de extensión se deben de escibrir dentro de clasesw estáticas y con un método estático, que recibe como parámetro el objeto que se pretende extender con una referencia de sí mismo.
namespace DataGridExtensions
{
public static class DataGridTools
{
public static void SelectLastRow(this DataGridView dataGrid){
//limpiar seleccion actual
dataGrid.ClearSelelection();
//obtener última fila
int lastRowsIndex = dataGrid.Rows.Count - 1;
//seleccinar la fila complete
dataGrid.Rows[lastRowsIndex].Selected = true;
//posicionar el cursor en la primera celda
dataGrid.CurrentCell = dataGrid.Rows[lastRowsIndex].Cells[0]; //ojo la celda debe de esta visible
//repintar el grid para que se vea la fila seleccinada
//en la posicion del la celda seleecionada
dataGrid.Refresh();
}
}
}
Y con ésto ya solo necesitamos importar el espacion de nombres DataGridExtensions para que en nuestro formulario winforms podamos desde cualquier data grid invocar al método .SelectLastRow() y a disfrutar de la regla DRY (don't repeat your self, no te repitas).
Paso tres. ¿creias que se había terminado?
Si analizar el código, pueden haber varias execciones:
1. No hay filas
2. No hay columnas visibles
Hay que tener en consideración éstas dos posibilidades, y minimizar la posiblidad de generar una excepción. Pero esto nos va a generar tener que escribir unas cuántas líneas más de código. Yo siempre escribo el blog lo más claro posible, si alguien conocer una forma de hacerlo con menos líneas, es bienvenido a comentar y compartir con todos cómo se hace con menos líneas de código.
Para solucionar la primera es bastante obvia, sólo tenemos que controlar con un simple IF que haya filas y listo. Pero para solucionar el segundo problema ya nos hace escribir unas cuántas lineas más y nos obliga a recorrer las celdas mientras no sean visibles. Por lo que ya podréis imaginar que necesitamos hacer. Un bucle, claro. Os pongo el código ya comentado y listo, porque aunque son unas cuántas líneas más de código, en un principio no es tanto.
namespace DataGridExtensions
{
public static class DataGridTools
{
public static void SelectLastRow(this DataGridView dataGrid){
//limpiar seleccion actual
dataGrid.ClearSelelection();
if (dataGrid.Rows.Count > 0){
//obtener última fila
int lastRowsIndex = dataGrid.Rows.Count - 1;
//seleccinar la fila complete
dataGrid.Rows[lastRowsIndex].Selected = true;
//buscar la primera columna (o celda) visible dentro de la fila
int colIndex = 0;
int totalColumns = dataGrid.Rows[lastRowsIndex].Cells.Count; //obtener el total de columnas
do{
if (!dataGrid.Rows[lastRowsIndex].Cells[colIndex].Visible == true){
colIndex++;
}
} while (dataGrid.Rows[lastRowsIndex].Cells[colIndex].Visible == true && colIndex < totalColumns)
//posicionar el cursor en la primera celda
if (dataGrid.Rows[lastRowsIndex].Cells[colIndex.Visible == true]){
//verificamos que realmente la celda seleccionada esta visible
dataGrid.CurrentCell = dataGrid.Rows[lastRowsIndex].Cells[colIndex]; //ojo la celda debe de esta visible
}
}
//repintar el grid para que se vea la fila seleccinada
//en la posicion del la celda seleecionada
dataGrid.Refresh();
}
}
}
Consideraciones
Al escribir el blog me he dado cuenta de que si se sale del Do While sin encontrar una celda visible es posible que el colIndex sea el total de las celdas, esto generara un error de fuera de rango, por lo que no esta de más comprober que colIndex < totalColumns.
Hasta la próxima amigos
Happy codding