Personalización condicional del DataGrid de Silverlight 2

Introducción

El control DataGrid de Silverlight 2 ofrece a los desarrolladores un mecanismo para presentar datos tabulares de una manera sencilla, ya que al ser un control atable a datos podemos indicar como fuente de datos cualquier objeto que implemente IList o IEnumerable.  Por este motivo y por el hecho de que automáticamente se ata a todas las propiedades del objeto se crearán las columnas correspondientes sin esfuerzo extra.

No obstante a lo anterior es un escenario común cambiar los colores de las filas de manera condicional, esto es, a partir de un valor o rango de valores de los datos cambiar sus características visuales de cada fila para resaltarlos.

En este artículo veremos cómo modificar la apariencia visual del DataGrid de manera condicional.

Desarrollo

Crearemos una nueva aplicación de Silverlight por medio de la plantilla en Visual Studio .NET 2008.  A esta aplicación le pondremos el nombre de EjemploDataGridCondicional.

Como fuente de datos para nuestra aplicación utilizaremos las clases Album y Albumes descritas en el artículo “Introducción a los Convertidores en Silverlight 2”.

Ya que el control DataGrid está implementado en un ensamblado externo (System.Windows.Controls.Data) necesitamos referenciar este ensamblado en nuestro proyecto y además importar el espacio de nombres xml asignándole un alias para poder identificar las clases incluídas en él de manera única. 

Asimismo también importaremos el espacio de nombres xml del proyecto EjemploDataGridCondicional para poder dar de alta nuestra fuente de datos como parte del diccionario de recursos del UserControl.  El siguiente fragmento muestra el código XAML modificado:

<UserControl x:Class="EjemploDataGridCondicional.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
    xmlns:app="clr-namespace:EjemploDataGridCondicional"
    Width="400" Height="300">
    <UserControl.Resources>
        <app:Albumes x:Key="albumes" />
    </UserControl.Resources>
...

Ahora ya estamos listos para poder crear una instancia del DataGrid.  El siguiente fragmento muestra el código necesario para crear un DataGrid el cual atamos a la fuente de datos implementada en el diccionario de recursos:

<Grid x:Name="LayoutRoot" Background="White" DataContext="{StaticResource albumes}">
    <data:DataGrid x:Name="lista" ItemsSource="{Binding}" />
</Grid>

Al ejecutar la aplicación, el resultado que obtenemos es el siguiente:

Como podemos observar el comportamiento predeterminado del DataGrid es atarse a todas las propiedades de la fuente de datos y además crear las columnas correspondientes automáticamente.

Colores condicionales para las filas

Para este ejemplo cambiaremos el color de cada álbum que tenga su fecha de lanzamiento anterior al 01/01/1999.  Para realizar esta funcionalidad crearemos un Convertidor de color, esto es, un Convertidor que reciba como entrada la fecha y regrese un color según el rango establecido.  El artículo “Introducción a los Convertidores en Silverlight 2” explica y detalla la creación de Convertidores.

Crearemos una clase llamada ConvertidorFechaColor dentro de un fólder llamado Convertidores en el proyecto de Silverlight. El siguiente código detalla esta clase:

public class ConvertidorFechaColor : IValueConverter
{
 
    #region IValueConverter Members
 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        DateTime entrada = (DateTime)value;
        SolidColorBrush resultado = new SolidColorBrush();
 
        if (entrada < DateTime.Parse("1999-01-01"))
        {
            resultado = new SolidColorBrush(Colors.Green);
        }
        else
        {
            resultado = new SolidColorBrush(Colors.White);
        }
 
        return resultado;
    }
 
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
 
    #endregion
}

Ahora bien, para utilizar esta clase dentro de nuestro DataGrid debemos definir nuestros propios elementos CellTemplate, los cuales definen la plantilla que se aplicará a cada celda cuando se esté atando a datos el control ya que esta clase soporta un DataTemplate. 

Además, necesitamos establecer la propiedad AutoGenerateColumns=”false” ya que la creación de columnas será ahora nuestra responsabilidad.  Cada columna la crearemos como un DataGridTemplateColumn ya que esta clase nos permite definir nuestra propia plantilla para las columnas.

Cada plantilla de columna tendrá como elemento raiz un Border, el cual será el elemento que cambiaremos de color en las filas.  A la propiedad Background del Border lo ataremos a la propiedad FechaLanzamiento de la fuente de datos, aplicando el Convertidor de color que escribimos anteriormente.  Dentro del Border colocaremos un TextBlock que muestre el texto correspondiente a la columna, atando a datos a la propiedad correspondiente.  El siguiente fragmento de código muestra el ejemplo de la columna “Titulo”:

<Border Background="{Binding FechaLanzamiento, Converter={StaticResource convertidorFechaColor}}">
    <TextBlock Text="{Binding Titulo}" />
</Border>

Si aplicamos el mismo concepto a cada una de las columnas el resultado sería el siguiente:

Además, podríamos reutilizar el Convertidor que construímos en el artículo anterior para poder formatear la fecha de lanzamiento adecuadamente, además del cambio de color que estamos aplicando.  Asimismo, podemos ir más allá con el Convertidor de fecha a color si pasamos como parámetro el tipo de color que queremos aplicar, esto es, si es para el fondo del Border o es para el color de la letra del TextBlock.  El siguiente fragmento de código muestra el Border con toda la funcionalidad completa:

<Border Background="{Binding FechaLanzamiento, Converter={StaticResource convertidorFechaColor}, ConverterParameter='FONDO'}">
                                <TextBlock Text="{Binding Banda}"
                                           Foreground="{Binding FechaLanzamiento, Converter={StaticResource convertidorFechaColor}}"
                                           />
                            </Border>

El resultado completo de nuestro proyecto es como se muestra:

Resumen

Por medio del elemento CellTemplate dentro de una columna de tipo DataGridTemplateColumn podemos llegar a obtener un grado de personalización avanzado dentro del control DataGrid.  Haciendo uso de Convertidores y lógica personalizada podemos determinar el color de fondo y fuente de cada una de las filas del DataGrid, por ejemplo para resaltar datos que caigan en un rango establecido u otro tipo de factor.

El código fuente de este ejemplo lo pueden descargar de la sección “Contenido” de La Liga Silverlight.