Search code examples
c#wpfbindingdatagrid

Binding DataGridTextColumn color from C# codebehind


Similar to WPF - help converting XAML binding expression to codebehind

I am attempting to use Binding to change the color of certain elements in a DataGridTextColumn. Because I need an arbitrary number of DataGrids in separate tabs, I am creating them iteratively in the codebehind. Here is my code for creating the column:

// create a value column
column = new DataGridTextColumn();
column.Binding = new Binding("Value");
BindingOperations.SetBinding(column, DataGridTextColumn.ForegroundProperty, new Binding("TextColor"));
listGrid.Columns.Add(column);

The Value binding works fine, but the TextColor property's getter never gets called.

The grid's ItemsSource property is set to a list of VariableWatcher objects, and here are some of its properties:

public bool Value
{
    get { return _variable.Value; }
}
// used to set DataGridTextColumn.Foreground
public Brush TextColor
{
    get
    {
        Color brushColor;
         if (_valueChanged)
            brushColor = Color.FromRgb(255, 0, 0);
        else
            brushColor = Color.FromRgb(0, 0, 0);
         return new SolidColorBrush(brushColor);
    }
}

VariableWatcher implements INotifyPropertyChanged as follows:

public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string info)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
}

In one of VariableWatcher's methods, I have the following lines:

_valueChanged = true;
NotifyPropertyChanged("Value");
NotifyPropertyChanged("TextColor");

Stepping over the "Value" line activates a breakpoint in the Value getter, and the Value text is updated in the display. However, stepping over the "TextColor" line does NOT activate the breakpoint in the TextColor getter, and the text color does not change. Any idea what's going on here?

EDIT: Here is the answer, thanks to Damascus. (I would have put this in a comment on his answer, but it wouldn't format my code properly.) I added this to the XAML file:

<Window.Resources>
    <Style x:Key="BoundColorStyle" TargetType="{x:Type TextBlock}">
        <Setter Property="Foreground" Value="{Binding TextColor}" />
    </Style>
</Window.Resources>

and in the C# code, I replaced the BindingOperations line with

column.ElementStyle = this.FindResource("BoundColorStyle") as Style;

Solution

  • Workaround for this:

    Create a style in your resources, looking like that:

    <Style x:Key="MyStyle" TargetType="{x:Type TextBlock}">
      <Setter Property="Foreground" Value="{Binding TextColor}" />
    </Style>
    

    And set this style in the ElementStyle property of your DataGridColumn, should be something like that in your code:

    column = new DataGridTextColumn();
    column.Style = this.FindResource("MyStyle") as Style;
    

    The reason for it being that ElementStyle directly works in the column's Content (ie. the TextBlock displaying a value)