1

Trying to setup the background of a cell dependend on a cell-object property in a WPF DataGrid I get an error, that the property is not found (but on the row-object):

System.Windows.Data Error: 40 : BindingExpression path error: 'IsOn' property not found on 'object' ''MyRow' (HashCode=48826322)'. BindingExpression:Path=IsOn; DataItem='MyRow' (HashCode=48826322); target element is 'DataGridCell' (Name=''); target property is 'NoTarget' (type 'Object')

I wonder, why the DataTrigger Binding is addressing the row object "MyRow", since the DataTrigger is defined for/inside a CellStyle.

XAML:

<DataGrid Name="tblTest" Grid.Column="2" IsReadOnly="True" AutoGenerateColumns="True">
    <DataGrid.CellStyle>
        <Style TargetType="{x:Type DataGridCell}">
            <Setter Property="Background" Value="PaleGreen" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding IsOn}" Value="True">
                    <Setter Property="Background" Value="Red"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGrid.CellStyle>
</DataGrid>

C#

class MyCell
{
    public MyCell( string v)
    {
        Value = v;
    }
    public string Value { get; set; }
    public bool IsOn { get => Value == "one";  }
    public override string ToString()
    {
        return Value;
    }
}

class MyRow
{
    public MyCell One { get; set;  }
    public MyCell Two { get; set;  }
}

void SetupTestTable()
{
    List<MyRow> data = new();
    data.Add(new MyRow
    {
        One = new MyCell("one"),
        Two = new MyCell("two")
    });
    tblTest.ItemsSource = data;
}

enter image description here

So how to bind against the cell object "MyCell" correctly?

2
  • Your datarow datacontext is Myrow instance and cells are displayed based on the properties defined on myrow instance. since these properties are complex type use should nagivate into the mycell and then access the IsOn property. <DataTrigger Binding="{Binding One.IsOn}" Value="True"> Commented Mar 24, 2021 at 10:32
  • Thanks Neelesh, I assume your approach could be used for tables with static layouts, but is not usable for DataGrids with enabled AutogenerateColumns. Commented Mar 24, 2021 at 12:59

1 Answer 1

2

DataGridCells have the same DataContext as DataGridRow - there are many obstacles to do differently in general-purpose manner. So single DataGrid.CellStyle won't work

I will use AutoGeneratingColumn to create cell styles for each column. However they will be based on existing style which is stored in DataGrid.Resources.

<DataGrid Name="tblTest" Grid.Column="2" IsReadOnly="True" 
          AutoGenerateColumns="True"
          AutoGeneratingColumn="tblTest_AutoGeneratingColumn">
    <DataGrid.Resources>
        <Style TargetType="{x:Type DataGridCell}" x:Key="ColoredCellStyle">
            <Setter Property="Background" Value="Cyan" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding Tag.IsOn, RelativeSource={RelativeSource Self}}" Value="True">
                    <Setter Property="Background" Value="Red"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGrid.Resources>
</DataGrid>

I'm using binding to Tag instead of DataContext, because DataContext is MyRow object. In Tag there will be MyCell objects. It is achieved in event handler:

private void tblTest_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    if (e.Column is DataGridTextColumn tc && tc.Binding is Binding binding)
    {
        // unique value for each column
        var property = binding.Path.Path;

        // DataGrid reference to get Resources
        var dg = (DataGrid)sender;

        // new cell style which inherits trigger from ColoredCellStyle and binds Tag to MyCell property
        var cellStyle = new Style
        {
            TargetType = typeof(DataGridCell),
            BasedOn = (Style)dg.Resources["ColoredCellStyle"],
            Setters =
            {
                new Setter
                { 
                    Property = DataGridCell.TagProperty, 
                    Value = new Binding(property)
                }
            }
        };

        tc.CellStyle = cellStyle;
    };
}

ColoredCells

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.