How to set Foreground of DataGrid Column with ValueConverter

SL_Logo If you need to change the Foreground (Color) of a DataGrid Column based on its value you will probably encounter a problem when you try to bind your DataGridTextColumn.Foreground property to a ValueConverter. I’ll show you how we do it and hopefully save you an hour or two.

Tools used?

Download Code: NetUsUp_Silverlight_TipsAndTricks.zip

See How To:

  1. Create a ValueConverter between DateTime? (Nullable DateTime) and Brush (Foreground property’s type).
  2. Bind a ValueConverter to a DataGrid Column’s Foreground property.

Creating our ValueConverter:

We create a ValueConverter which return a Black SolidColorBrush unless the DateTime value matches today or earlier, in which case it returns Red.

Note: Since we have no need to convert the value back, we just return the value in the ConvertBack() method.

   1:  /// <summary>
   2:      /// Converts between Nullable DateTime and Color Brush
   3:      /// </summary>
   4:      public class DateTimeToColorValueConverter: IValueConverter
   5:      {
   6:          /// <summary>
   7:          /// Converts value (in our case DateTime?) into a Brush
   8:          /// for binding to Foreground of text element.
   9:          /// </summary>
  10:          /// <param name="value"></param>
  11:          /// <param name="targetType"></param>
  12:          /// <param name="parameter"></param>
  13:          /// <param name="culture"></param>
  14:          /// <returns></returns>
  15:          public object Convert(object value, 
  16:                                Type targetType, 
  17:                                object parameter, 
  18:                                System.Globalization.CultureInfo culture)
  19:          {
  20:              SolidColorBrush result = new SolidColorBrush(Colors.Black);
  21:   
  22:              DateTime dt = DateTime.MinValue;
  23:              if (DateTime.TryParse(value.ToString(), out dt))
  24:              {
  25:                  if (dt < DateTime.Now)
  26:                  {
  27:                      result = new SolidColorBrush(Colors.Red);
  28:                  }
  29:              }
  30:   
  31:              return result;
  32:          }
  33:   
  34:          public object ConvertBack(object value, 
  35:                                    Type targetType, 
  36:                                    object parameter, 
  37:                                    System.Globalization.CultureInfo culture)
  38:          {
  39:              //We don't need to convert back, so we just return the value.
  40:              return value;
  41:          }
  42:      }

Binding to the DataGridTextColumn Foreground property:

If you try to bind your DataGridTextColumn Foreground property to this value converter, you will get an error in runtime which basically means that you cannot bind to the Foreground property.

A quick look in the MSDN documentation: DataGridTextColumn.Foreground will show us that this property is NOT a dependency property. hmmm… why not? we’ll have to ask the Silverlight Team, but we need a solution, so what can we do?

Binding to a DataGridTemplateColumn Foreground:

The fastest solution, is to replace the DataGridTextColumn with a DataGridTemplateColumn. Inside this column we will use a TextBlock which has a Foreground property which IS a dependency property – yeay!

here is the Xaml:

   1:  <!--
   2:   PROBLEM:
   3:  The DataGridTextColumn's Forground property is NOT a dependency 
   4:   propert so we cannot bind our ValueConverter to it.
   5:                  
   6:  SOLUTION:
   7:  We use a DataGridTemplateColumn with a TextBlock for the value. 
   8:   Foreground is a Dependency property on TextBlock so binding to a Value Converter works.
   9:                  
  10:   TIP:
  11:   You could also create your own DataGridTextColumn (using inheritance) and add your own
  12:  Dependency property for binding to Foreground...
  13:   -->
  14:  <sdk:DataGridTemplateColumn x:Name="DateTime2" Header="Date Time 2" MinWidth="100">
  15:          <sdk:DataGridTemplateColumn.CellTemplate>
  16:                  <DataTemplate>
  17:                      <TextBlock Text="{Binding Path=DateTime}" 
  18:                                         Foreground="{Binding Path=DateTime,
  19:                                         Converter={StaticResource dateTimeToColorValueConverter}}" 
  20:                                         VerticalAlignment="Center" />
  21:                   </DataTemplate>
  22:           </sdk:DataGridTemplateColumn.CellTemplate>
  23:  </sdk:DataGridTemplateColumn>

So there we have it. A simple solution to a missing Dependency property.

Tip: You could have inherited DataGridTextColumn and created your own with a Bindable Foreground property – but I will leave that challenge to you, if you have the time.

Thanks for reading, please post any comments you may have.

Jonathan.

Tags: ,


Leave a Reply

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

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>