Search code examples
c#wpfdata-bindingdatagridxaml-binding

WPF DataGrid cell slyle change after update


I have a DataGrid with dynamicaly generated columns and I need to change style of cells whose values have changed after some manipulations.

The ItemsSource for DataGrid is defined as List<MyTableRow>, where

public class MyTableRow
{
    private string[] _values;
    private string _rowHeader;

    // getters and setters here
}

DataGrid columns are generated with following code:

for (int i = 0; i < source[0].Values.Length; i++)
{
    var col = new DataGridTextColumn();
    var binding = new Binding("Values[" + i + "]");
    col.Binding = binding;
    col.CanUserSort = false;
    this.dataGrid.Columns.Add(col);
    this.dataGrid.Columns[i].Header = columnNames[i];
}

Resulting DataGrid looks like this

The problem arises when I try to highlight (bold text or colored background) cells whose values in ItemsSource have changed. This i sthe point where my question splits into two:

  1. Is there some "built-in" way to do smth with changed cells? (maybe with ObservableColletion or smth else)
  2. If no, how can i highlight separate cells based either on their indexes or their values

I tried to do this with xaml styles and/or triggers, but it turned out that i do not know what value blinding should I pass to converter

<Style TargetType="TextBlock">
    <Setter Property="Background" 
            Value="{Binding <!-- some proper binding here -->, 
                    Converter={StaticResource ValueToBrushConverter}}"/>
</Style>

Other solutions found on SO either have the same "problem" with binding or just don't work. What can I do to highlight just one cell and not whole row/column? I can change ItemsSource, MyTableRow fields and/or columns' generation code, if necessary

Can anyone please help me out? Been a few days since I stuck with this problem


UPDATE Found solution



Solution

  • Finally find out how to do what I want. The solution is kinda "dirty", but works fine for me. I added non-breaking space character to every cell I need to highlight

    private const string NBSP = "\u00A0"

    All that's left to do after that is to create value converter. So I added MultiBinding in my XAML:

    <DataGrid.CellStyle>
        <Style TargetType="{x:Type DataGridCell}">
            <Setter Property="Background">
                <Setter.Value>
                    <MultiBinding Converter="{StaticResource ValueToBrushMultiConverter}" >
                        <MultiBinding.Bindings>
                            <Binding RelativeSource="{RelativeSource Self}" />
                            <Binding RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridRow}}" />
                        </MultiBinding.Bindings>
                     </MultiBinding
                </Setter.Value>
            </Setter>
        </Style>
    </DataGrid.CellStyle>
    

    Сonverter defined as:

    public class ValueToBrushMultiConverter : IMultiValueConverter
        {
            private const string NBSP = "\u00A0";
            public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                var cell = (DataGridCell)values[0];
                var dgRow = (DataGridRow)values[1];
    
                var test = (dgRow.Item as TableRow<string, string>).Values[cell.Column.DisplayIndex];
    
                if (test.Contains(NBSP))
                    return System.Windows.Media.Brushes.PaleGreen;
                return DependencyProperty.UnsetValue;           
            }
    
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
            {
                throw new NotSupportedException();
            }
        }
    

    Hope this helps someone!