views:

506

answers:

1

I am trying to change the color of a cell to Yellow if the value has been updated in the DataGrid.

My XAML:

<toolkit:DataGrid x:Name="TheGrid"
                  ItemsSource="{Binding}"
                  IsReadOnly="False"
                  CanUserAddRows="False"
                  CanUserResizeRows="False"
                  AutoGenerateColumns="False"
                  CanUserSortColumns="False"                             
                  SelectionUnit="CellOrRowHeader" 
                  EnableColumnVirtualization="True" 
                  VerticalScrollBarVisibility="Auto"
                  HorizontalScrollBarVisibility="Auto">
    <toolkit:DataGrid.CellStyle>
        <Style TargetType="{x:Type toolkit:DataGridCell}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsDirty}" Value="True">
                    <Setter Property="Background" Value="Yellow"/>
                 </DataTrigger>
            </Style.Triggers>
        </Style>
    </toolkit:DataGrid.CellStyle>
</toolkit:DataGrid>

The grid is bound to a List of arrays (displaying a table of values kind of like excel would). Each value in the array is a custom object that contains an IsDirty dependency property. The IsDirty property gets set when the value is changed.

When i run this:

  • change a value in column 1 = whole row goes yellow
  • change a value in any other column = nothing happens

I want only the changed cell to go yellow no matter what column its in. Do you see anything wrong with my XAML?

+1  A: 

The reason this happens is because DataContext is set at row level and doesn't change for each DataGridCell. So when you bind to IsDirty it binds to the property of row-level data object, not cell-level one.

Since your example shows that you have AutoGenerateColumns set to false, I assume that you generate columns yourself have something like DataGridTextColumn with Binding property set to binding to actual value field. To get cell style changed to yellow you'd have to change CellStyle on each DataGridColumn like this:

foreach (var column in columns)
{
    var dataColumn =
        new DataGridTextColumn
            {
                Header = column.Caption,
                Binding = new Binding(column.FieldName),
                CellStyle = 
                new Style
                    {
                        TargetType = typeof (DataGridCell),
                        Triggers =
                            {
                                new DataTrigger
                                    {
                                        Binding = new Binding(column.FieldName + ".IsDirty"),
                                        Setters =
                                            {
                                                new Setter
                                                    {
                                                        Property = Control.BackgroundProperty,
                                                        Value = Brushes.Yellow,
                                                    }
                                            }
                                    }
                            }
                    }
            };
    _dataGrid.Columns.Add(dataColumn);
}

You can experiment with changing DataContext of each cell using DataGridColumn.CellStyle. Perhaps only then you'll be able to bind cell's to 'IsDirty' directly from grid-level style like you do without doing it for each column individually. But I don't have actual data model you have to test this.

repka
Awesome! This worked exactly how I needed it to. The only thing I had to change was adding a Value=true to the DataTrigger(so it triggers when IsDirty is true)
KrisTrip