Formatear y resaltar valores en el control DataGridView con el evento CellFormatting (I)
Aunque las capacidades de formato que proporciona el control DataGridView puedan resultar, en principio, sencillas de implementar, con cierta regularidad encuentro en los foros de Microsoft consultas referentes a cómo conseguir que la información de las celdas que este control muestra sea personalizable, para adaptarse a las exigencias del usuario.
DataGridView es un control potente, que nos permite visualizar una gran cantidad de datos en forma tabular, pero su aspecto predeterminado no resulta demasiado atractivo si lo que necesitamos es resaltar ciertos elementos para llamar la atención del usuario.

Sin embargo esto no quiere decir que carezca de la funcionalidad necesaria para ofrecer, si es menester, una imagen lo suficientemente atrayente.
Como ejemplo de dichas características, en esta serie de artículos abordaremos el evento CellFormatting, que combinado con las capacidades de creación y aplicación de estilos visuales, ofrece al programador un potente y flexible mecanismo que le permite formatear y resaltar los datos presentados.
CellFormatting es un evento que se desencadena para cada celda del DataGridView que es dibujada. Su funcionamiento por defecto consiste en convertir el dato a mostrar en el valor más adecuado a efectos de presentación (habitualmente texto). Pero dado que para ciertos valores, una manipulación más elaborada del dato puede ser necesaria, se expone el evento al programador para que pueda adaptarlo a sus necesidades.
Seguidamente vamos a mostrar un conjunto de los modos más habituales en que podemos formatear los valores de las celdas del control utilizando este evento.
El proyecto base de los ejemplos
Una vez creado un nuevo proyecto en Visual Studio que nos sirva como banco de pruebas, y dado que para cada ejemplo a mostrar utilizaremos un formulario diferente, emplearemos el formulario por defecto que incluye el proyecto como "lanzadera" del resto de formularios, donde añadiremos un ListBox con los nombres de cada tipo de operación de formato junto a un botón para abrir el correspondiente formulario.

A continuación podemos ver el código necesario para las mencionadas operaciones.
private void btnVisualizar_Click(object sender, EventArgs e)
{
Form frmFormulario;
switch (this.listBox1.SelectedIndex)
{
case 0:
frmFormulario = new frmFormatoBasico();
frmFormulario.Show();
break;
case 1:
frmFormulario = new frmFormatoColores();
frmFormulario.Show();
break;
case 2:
frmFormulario = new frmFormatoCondicional();
frmFormulario.Show();
break;
case 3:
frmFormulario = new frmFormatoCondicionalCambiarTodo();
frmFormulario.Show();
break;
case 4:
frmFormulario = new frmFormatoIndirecto();
frmFormulario.Show();
break;
case 5:
frmFormulario = new frmFormatoIndirectoImagen();
frmFormulario.Show();
break;
case 6:
frmFormulario = new frmFormatoTipoDato();
frmFormulario.Show();
break;
case 7:
frmFormulario = new frmFormatoExpresionRegulada();
frmFormulario.Show();
break;
case 8:
frmFormulario = new frmFormatoFilaCompleta();
frmFormulario.Show();
break;
}
}
Preparación de los datos a visualizar
En todos los ejemplos mostrados vamos a utilizar una consulta contra la tabla DimCostumer, perteneciente a la base de datos AdventureWorksDW. Para evitar en cada formulario del proyecto la repetición del código que conecta con la fuente de datos y construye el DataSet encargado de rellenar el control DataGridView, vamos a crear una clase con un método estático, que nos devuelva la mencionada tabla, la cual asignaremos a la propiedad DataSource del control DataGridView.
class ConstruirDatos
{
public static DataTable ObtenerTabla()
{
// crear la sentencia sql para obtener las filas
StringBuilder sbSQL = new StringBuilder();
sbSQL.Append("SELECT CustomerAlternateKey, ");
sbSQL.Append("Title, FirstName, LastName, ");
sbSQL.Append("BirthDate, YearlyIncome, Gender ");
sbSQL.Append("FROM DimCustomer ");
sbSQL.Append("WHERE Title IS NOT NULL");
// conectar con la base de datos,
// ejecutar la consulta y devolver el resultado
SqlConnection cnConexion = new SqlConnection();
cnConexion.ConnectionString = "Data Source=localhost;" +
"Initial Catalog=AdventureWorksDW;" +
"Integrated Security=True";
SqlCommand cmdComando = new SqlCommand(sbSQL.ToString(), cnConexion);
SqlDataAdapter daAdaptador = new SqlDataAdapter(cmdComando);
DataSet dsDatos = new DataSet();
cnConexion.Open();
daAdaptador.Fill(dsDatos, "DimCustomer");
cnConexion.Close();
return dsDatos.Tables[0];
}
}
Formato básico. La primera aproximación a CellFormatting
Nuestro primer ejemplo consistirá en aplicar un formato a los datos que con mayor frecuencia se prestan a realizar este tipo de acción: fechas y números; por lo que tras crear en primer lugar el manipulador de evento para CellFormatting, procederemos a dotarle de funcionalidad.
El evento CellFormatting recibe como parámetro un tipo DataGridViewCellFormattingEventArgs, cuyas propiedades serán las que nos proporcionen la información y soporte para aplicar el formato necesario en cada ocasión.
Debemos comenzar comprobando que la columna sobre la que se está produciendo el evento corresponde a aquella que necesitamos formatear, para lo que utilizaremos la propiedad DataGridViewCellFormattingEventArgs.ColumnIndex aplicada a la colección Columns del DataGridView. Una vez realizada esta verificación, con la propiedad DataGridViewCellFormattingEventArgs.CellStyle accederemos a un tipo DataGridViewCellStyle, cuyos miembros serán los que nos ofrezcan todas las posibilidades de formato, efectos de colores, alineación, etc., disponibles para adaptar la visualización del dato existente en la celda.
En este caso concreto emplearemos la propiedad DataGridViewCellFormattingEventArgs.CellStyle.Format para asignar una cadena de formato sobre las columnas BirthDate y YearlyIncome del control. Dicha cadena puede estar basada en una de las predefinidas por la plataforma .Net Framework, o ser una personalizada, construida por el programador empleando los caracteres de formato especiales disponibles a tal efecto. En el siguiente bloque de código mostramos un ejemplo de cada tipo.
public partial class frmFormatoBasico : Form
{
public frmFormatoBasico()
{
InitializeComponent();
}
//....
private void frmFormatoBasico_Load(object sender, EventArgs e)
{
this.dataGridView1.DataSource = ConstruirDatos.ObtenerTabla();
}
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
// formatear fecha
if (this.dataGridView1.Columns[e.ColumnIndex].Name == "BirthDate")
{
e.CellStyle.Format = "D";
}
// formatear valor numérico monetario
if (this.dataGridView1.Columns[e.ColumnIndex].Name == "YearlyIncome")
{
e.CellStyle.Format = "#,#.0 €";
}
}
}
En la siguiente imagen podemos apreciar el resultado de esta operación de formato.

Aplicando colores al formato
Además de los procedimientos de formato, que como acabamos de ver, modifican la manera en que el dato es mostrado, podemos cambiar otros aspectos en la visualización de la celda tales como la combinación de colores -en estado normal y seleccionado-, alineación del contenido, etc.
Las propiedades BackColor, ForeColor, SelectionBackColor, SelectionForeColor y Alignment, de la clase DataGridViewCellStyle, nos ofrecen la posibilidad de manipular estas características, tal y como vemos en el siguiente bloque de código. Nótese que para los colores en estado seleccionado de la columna LastName, aplicamos una técnica consistente en asignar la combinación de colores normales pero en sentido inverso.
private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (this.dataGridView1.Columns[e.ColumnIndex].Name == "FirstName")
{
// aplicar colores a celda en estado normal
e.CellStyle.BackColor = Color.MediumTurquoise;
e.CellStyle.ForeColor = Color.DarkOrchid;
// aplicar colores a celda en estado seleccionado
e.CellStyle.SelectionBackColor = Color.DarkOliveGreen;
e.CellStyle.SelectionForeColor = Color.Yellow;
// establecer alineación del texto
e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
}
if (this.dataGridView1.Columns[e.ColumnIndex].Name == "LastName")
{
// aplicar colores a celda en estado normal
e.CellStyle.BackColor = Color.MediumSeaGreen;
e.CellStyle.ForeColor = Color.LightYellow;
// aplicar colores a celda en estado seleccionado
e.CellStyle.SelectionBackColor = e.CellStyle.ForeColor;
e.CellStyle.SelectionForeColor = e.CellStyle.BackColor;
// establecer alineación del texto
e.CellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
}
}
El efecto del uso de estas propiedades de estilo podemos apreciarlo en la siguiente imagen, donde vemos las celdas con los colores asignados para su estado normal y seleccionado.

El código fuente de los ejemplos puede descargarse desde los siguientes enlaces: C# y VB. Estos proyectos contienen los ejemplos al completo pertenecientes a toda esta serie de artículos.
En la siguiente entrega, más características interesantes de este evento.
Un saludo.