Conditionally Formatting Cells in XamDataGrid

Date: 4/24/2011
Version Used: 2010.2

The Infragistics WPF data grid control (XamDataGrid) is well known for its capabilities of producing polished reports, tables, ledgers, product listings, and more. One important feature that this article will demonstrate is the ability to conditionally format cells.
Introduction
If you’re not familiar with the meaning of conditionally formatted cells, imagine looking at a data grid that has several columns and rows. The monotone appearance can be very hard to read and locate important values. Conditionally formatting these cell values offer easier readability and a flexible method for achieving the visual contrast that will draw attention from the viewer’s eyes.

WPF Value Converters
To change monotone cell values to something more visual stimulating, we’ll make use of two value converter interfaces that can be found in the .NET framework called IValueConverter and IMultiValueConverter. As the names suggest IValueConverter converts a single value and IMultiValueConverter can convert an array of values based on custom logic.
To start we’ll create a class that inherits the IMultiValueConverter interface with the Convert and ConvertBack methods generated from the inheritance.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
namespace xamDataGrid_ConditionalFormatting.ConditionalConverters
{
    class TotalSalesColorConverter: IMultiValueConverter
    {
        #region IMultiValueConverter Members

        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (values != null)
            {
                if (values[0] != DependencyProperty.UnsetValue && values[1] != DependencyProperty.UnsetValue)
                {
                    //Insert your custom logic here and return a SolidColorBrush
                }
            }
            return Binding.DoNothing;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}

In the sample project included with this article, custom logic was used to compare the estimated sales versus the total sales, which then returns a green SolidColorBrush for sales above estimate, and a red SolidColorBrush for sales below estimate. The Convert method below shows our custom logic.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (values != null)
            {
                if (values[0] != DependencyProperty.UnsetValue && values[1] != DependencyProperty.UnsetValue)
                {
                    Decimal EstimatedSales = (Decimal)values[0];
                    Decimal TotalSales = (Decimal)values[1];

                    if (EstimatedSales > TotalSales)
                        return new SolidColorBrush(Colors.Red);
                    else
                        return new SolidColorBrush(Colors.Green);
                }
            }
            return Binding.DoNothing;
        }

Next, we’ll create the class to inherit from IValueConverter and take a look at the skeleton. You’ll notice that the structure of the Convert method is nearly identical to IMultiValueConverter.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
namespace xamDataGrid_ConditionalFormatting.ConditionalConverters
{
    class YearColorConverter: IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value == null)
                return Binding.DoNothing;

            //Insert your custom logic here and return a Color
            //Typically in this custom logic you'll use a switch/case or if statement to
            //   process the correct data type.

            return Binding.DoNothing;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}

For the sample project we used the Year column to check for a specific year value and returned a Color to set the background of the cell.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value == null)
                return Binding.DoNothing;

            if (value is String)
            {
                String Year = (String)value;
                switch (Year)
                {
                    case "2010":
                        return Colors.LightBlue;
                    case "2011":
                        return Colors.LightGray;
                    default:
                        return Colors.White;
                }
            }
            return Binding.DoNothing;
        }

XAML Integration

Now that we have the two necessary classes created for our conversion to a conditionally formatted cell, we’ll have to add the namespace to the class at the top of our XAML source.


1
xmlns:cc="clr-namespace:xamDataGrid_ConditionalFormatting.ConditionalConverters"

With the namespace now in place we can add references to each converter inside the Windows.Resources tags. This gives us the ability to use the converters as a static resource in the parts of XAML where we need it as you’ll see coming up.


1
 

To make use of the converters we need to create the Style/Setter tag groups inside the XamDataGrid.Resources tags to target the CellValuePresenter class. From that point you can reference the necessary property in the Setter tag. In this article we’re using Foreground property for the total sales conversion against the estimated sales, and Background property for the year column.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
                <!--
                    <Setter Property="Foreground">
                        <Setter.Value>
                            <MultiBinding Converter="{StaticResource totalSalesColorConverter}">
                                <Binding Path="DataItem.SalesEstimate" />
                                <Binding Path="DataItem.TotalSales" />
                            </MultiBinding>
                        </Setter.Value>
                    </Setter>

-->
                <!--
                    <Setter Property="Background">
                        <Setter.Value>
                            <SolidColorBrush Color="{Binding Path=DataItem.Year, Converter={StaticResource yearColorConverter}}" />
                        </Setter.Value>
                    </Setter>

-->

The final step in wiring up the conditional formatting happens inside the Field.Settings tags. By setting the CellValuePresenterStyle as the static resource key we created in XamDataGrid.Resources our custom styling will process the converter binding and give our grid some eye catching color.


1
 

Conclusion

That’s all there is to it! Now that you see how to conditionally format cells of the XamDataGrid you can easily begin to expand on this concept if you need further formatting by making use of the other properties that can be found inside the CellValuePresenter class along with the Setter tags.

Download the Source Code