【问题标题】:How do I change the color of Cell in WPF DataGrid based on a property of the object in itemsource?如何根据 itemsource 中对象的属性更改 WPF DataGrid 中 Cell 的颜色?
【发布时间】:2011-03-26 22:21:03
【问题描述】:

我有一个非常简单的对象,称为 CellData。定义为:

public sealed class CellData
{
    internal string DisplayText
    {
        get;
        set;
    }

    public string Color
    {
        get;
        set;
    }

    public override string ToString()
    {
        return this.DisplayText;
    }
}

我可以使用 WPF 工具包 DataGrid 很好地显示它。但是,我希望能够根据单元格中的数据更改每个单元格的背景颜色。我无法理解我需要执行哪种类型的绑定,因为我看不到要访问 DataTrigger 中的 CellData 对象。我尝试了以下方法和其他几种变体,但无法正常工作:

            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=(CellData).Color, Mode=OneWay}" Value="1">
                <Setter Property="Background" Value="Red" />
                <Setter Property="Foreground" Value="White" />
            </DataTrigger>

我对 XAML 数据绑定非常陌生,因此我们将不胜感激任何建议。谢谢。

【问题讨论】:

    标签: c# wpf datagrid wpftoolkit


    【解决方案1】:

    我猜您有一个包含多个 CellData 对象的 RowData 对象,您已将 DataGrid 的 ItemsSource 绑定到 RowData 对象列表,并且您正在使用绑定到 RowData 上的属性的 DataGridTextColumns 或其他 DataGridBoundColumns,也许只是通过使用 AutoGenerateColumns="True"。

    问题在于单元格的 DataContext 实际上是 RowData,而不是 CellData。 Binding 仅用于 TextBlock 和 TextBox 的 Text 属性。如果您希望触发器基于 RowData 对象的其他属性,这很有用,但在像您这样具有丰富的单元格数据数据结构的场景中会很困难。

    如果您要显式创建列,则可以在触发器中再次使用该列的属性:

    <DataGridTextColumn Binding="{Binding Foo}">
        <DataGridTextColumn.CellStyle>
            <Style TargetType="DataGridCell">
                <Style.Triggers>
                    <!-- DataContext is the row, so start 
                         binding path with Foo property -->
                    <DataTrigger Binding="{Binding Foo.Color}" Value="1">
                        <Setter Property="Background" Value="Red" />
                        <Setter Property="Foreground" Value="White" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGridTextColumn.CellStyle>
    </DataGridTextColumn>
    

    不幸的是,这不会让您在列之间共享样式,因为它特定于列名。如果您想这样做,您可能需要创建一个自定义 DataGridColumn 子类,该子类具有 Binding 类型的属性,该属性应用于 GenerateElement 和 GenerateEditingElement 返回的对象的 DataContext 属性。

    (在示例中使用 Self 的 RelativeSource 绑定会为您提供可视树中的元素而不是其 DataContext,这无助于您访问 CellData 对象。)

    【讨论】:

    • Maurizio Reginelli - 我不确定我是否跟随。 Quartermeister,我所做的是创建一个 DataTable,然后将 DataGrid 的 DataContext 设置为 DataTable 并将 AutoGenerate 设置为 true。问题是列和行都是在运行时创建的。最重要的是,我不认为我想将样式应用于列,因为我不想更改列中所有单元格的颜色,只是一些。我怀疑这里的问题是我还不完全了解绑定和 XAML 是如何工作的。我会继续研究,但如果您有任何其他建议,那就太好了。
    • @Nick:将 CellStyle 应用于列将分别将触发器应用于每个单元格,因此它可能是您想要的。如果您使用自动生成的列会很困难,因为单元格的 DataContext 将是一个 DataRow,而不是单个单元格的值。只有 TextBlock 或 TextBox 的 Text 属性绑定到特定列。您可能可以通过处理 AutoGeneratingColumn 事件并根据当前列应用带有触发器的样式来做到这一点,但是您将在代码中执行大量表示层逻辑。
    • Quartermeister - 我回去手动定义了列,然后使用了上面的提示。现在一切正常,谢谢!这很奇怪,也许是因为我对 WPF 不是很熟悉,但我觉得 WPF DataGrid 是一种倒退。
    【解决方案2】:

    您可以使用 ValueConverter:在单元格的背景颜色和对象的 Color 属性之间创建绑定,然后添加 ValueConverter 以确保您的数据正确转换为设置背景所需的对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-22
      • 2019-02-16
      • 2012-04-16
      • 1970-01-01
      • 2021-05-31
      • 1970-01-01
      • 2022-08-10
      • 1970-01-01
      相关资源
      最近更新 更多