WPF DataGrid - 如何设置正确的 DataTrigger 绑定到单元格的数据源(而不是行的源)

Posted

技术标签:

【中文标题】WPF DataGrid - 如何设置正确的 DataTrigger 绑定到单元格的数据源(而不是行的源)【英文标题】:WPF DataGrid - How to setup correct DataTrigger binding to cell's data source (and not row's source) 【发布时间】:2021-06-20 23:45:08 【问题描述】:

尝试根据 WPF DataGrid 中的单元格对象属性设置单元格的背景,但出现错误,找不到该属性(但在行对象上):

System.Windows.Data 错误:40:BindingExpression 路径错误:在“对象”“MyRow”(HashCode=48826322)上找不到“IsOn”属性。绑定表达式:路径=IsOn; DataItem='MyRow' (HashCode=48826322);目标元素是'DataGridCell'(名称='');目标属性是“NoTarget”(类型“对象”)

我想知道,为什么 DataTrigger 绑定正在寻址行对象“MyRow”,因为 DataTrigger 是为/在 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;

那么如何正确绑定单元格对象“MyCell”呢?

【问题讨论】:

您的数据行数据上下文是 Myrow 实例,并且单元格根据在 myrow 实例上定义的属性显示。由于这些属性是复杂类型,因此使用应该导航到 mycell,然后访问 IsOn 属性。 感谢 Neelesh,我认为您的方法可用于具有静态布局的表,但不适用于启用 AutogenerateColumns 的 DataGrids。 【参考方案1】:

DataGridCells 与 DataGridRow 具有相同的 DataContext - 以通用方式做不同的事情有很多障碍。所以单个 DataGrid.CellStyle 不起作用

我将使用AutoGeneratingColumn 为每一列创建单元格样式。但是,它们将基于存储在 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>

我使用绑定到 Tag 而不是 DataContext,因为 DataContext 是 MyRow 对象。在Tag 中会有MyCell 对象。它是在事件处理程序中实现的:

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;
    ;

【讨论】:

以上是关于WPF DataGrid - 如何设置正确的 DataTrigger 绑定到单元格的数据源(而不是行的源)的主要内容,如果未能解决你的问题,请参考以下文章

将按钮添加到 WPF DataGrid

wpf datagrid 滚动条如何设置宽度和颜色

WPF DataGrid MaxWidth 设置为 100% 可用空间

wpf datagrid 单元格如何默认单击一次点中

WPF DataGrid 如何动态设置单行高度

Wpf:如何从嵌套的 DataGrid 中绑定 SelectedItem