如何使用WPF Toolkit Datagrid更改单元格的背景颜色

23

我正在使用WPF工具包数据网格,并且我想基于单元格的内容而不是行设置单元格的背景颜色。

为了简单起见,假设列名为Foo,当Foo为1时,我想将单元格的背景设置为蓝色,当Foo为2时为红色,当Foo为3时为黄色,当Foo大于3时为绿色。

如果我能做到这一点,我相信我能解决任何更复杂的情况。

4个回答

41

您可以使用样式和数据触发器来实现此操作。只需使用默认背景属性(在本例中为绿色)设置ElementStyle,并为其他情况添加DataTriggers:

<DataGridTextColumn Binding="{Binding WhateverIWantToDisplay}" >
  <DataGridTextColumn.ElementStyle>
    <Style TargetType="{x:Type TextBlock}">

      <Setter Property="Background" Value="Green" />

      <Style.Triggers>
        <DataTrigger Binding="{Binding Foo}" Value="1">
          <Setter Property="Background" Value="Blue" />
        </DataTrigger>

        <DataTrigger Binding="{Binding Foo}" Value="2">
          <Setter Property="Background" Value="Red" />
        </DataTrigger>

        <DataTrigger Binding="{Binding Foo}" Value="2">
          <Setter Property="Background" Value="Yellow" />
        </DataTrigger>

      </Style.Triggers>
    </Style>
  </DataGridTextColumn.ElementStyle>
</DataGridTextColumn>

另一种方法是使用带有转换器的绑定:

<DataGridTextColumn Binding="{Binding WhateverIWantToDisplay}" >
  <DataGridTextColumn.ElementStyle>
    <Style TargetType="{x:Type TextBlock}">

      <Setter Property="Background"
        Value="{Binding Foo, Converter={x:Static my:FooToColorConverter.Instance}}" />

    </Style>
  </DataGridTextColumn.ElementStyle>
</DataGridTextColumn>

使用这个转换器:

public class FooToColorConverter : IValueConverter
{
  public static readonly IValueConverter Instance = new FooToColorConverter();
  public object Convert(object value, ...
  {
    int foo = (int)value;
    return
      foo==1 ? Brushes.Blue :
      foo==2 ? Brushes.Red :
      foo==3 ? Brushes.Yellow :
      foo>3 ? Brushes.Green :
        Brushes.Transparent;  // For foo<1
  }
  public object ConvertBack(...
  {
    throw new NotImplementedException();
  }
}
请注意,serge_gubenko给出的答案也可以工作,但只有当你的Foo属性值从不改变时才有效。这是因为Color属性的getter方法只会被调用一次。可以通过将Color更改为只读DependencyProperty并在分配Foo时更新它来改进他的解决方案,但通常在数据模型中拥有UI特定信息(如颜色)是一个坏习惯,因此不建议这样做。

1
非常感谢。我觉得WPF很难处理,因为它倾向于隐藏错误,并且当您的代码不正确时什么也不做。但是当它工作时,并且当您知道自己在做什么时,它非常快速和易于使用。我可以诚实地说,WPF是我使用过的任何技术中学习曲线最陡峭的。无论如何,再次感谢。我选择了转换器,因为它给了我最大的灵活性。 - Jonathan Beerhalter

7

您可以通过定义列的ElementStyle并将textblock背景绑定到数据元素的颜色属性来实现此目的。以下是一个例子:

DataGridTextColumn xaml:

<DataGridTextColumn Width="SizeToCells"   
                       MinWidth="150" 
                       Binding="{Binding Name}">

    <DataGridTextColumn.ElementStyle>
        <Style TargetType="{x:Type TextBlock}">
            <Setter Property="TextBlock.Background" Value="{Binding Color}" />
        </Style>
    </DataGridTextColumn.ElementStyle>
</DataGridTextColumn>

数据项声明:
public class TestItem
{
    public TestItem(int foo)
    {
        Foo = foo;
    }

    public int Foo { get; set; }
    public Brush Color
    {
        get
        {
            Color color = Colors.Green;
            switch (Foo)
            {
                case 1: color = Colors.Red; break;
                case 2: color = Colors.Yellow; break; 
            }
            return new SolidColorBrush(color);
        }
    }
}

希望这能帮到您,敬礼。

如果Foo的值在网格显示后发生变化,这将无法工作:单元格颜色将不会更新。请查看我的答案以获取更多细节。 - Ray Burns
而且,如果在显示网格时Foo发生更改(例如,由于数据绑定),也不会影响。 - greenoldman
虽然这是旧代码,但你只需要在TestItem类中实现INotifyPropertyChanged接口,就可以通知UI颜色的变化并修复它。 - Tafari

3

一种稍微不同的方法是,不是针对TextBlock元素进行定位(通常会在控件周围留下边框),而是直接定位到DataGridCell本身。在我的情况下,我已经有一个想要继承的样式,只需要根据值更改背景颜色:

<DataGridTextColumn 
    Width="*"
    Header="Status"
    Binding="{Binding EventStatus, Converter={StaticResource DescriptionAttributeConverter}}"
    HeaderStyle="{StaticResource DataGridColumnHeaderStyleCenterAligned}">

    <DataGridTextColumn.CellStyle>
        <Style TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource DataGridCellStyleCenterAligned}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding EventStatus}" Value="1">
                    <Setter Property="Background" Value="Green" />
                </DataTrigger>

                <DataTrigger Binding="{Binding EventStatus}" Value="2">
                    <Setter Property="Background" Value="Red" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGridTextColumn.CellStyle>
</DataGridTextColumn>

也许对于和我一样的人有所帮助。

1

如果你的项目从INotifyPropertyChanged继承,那么serge_gubenko将会很好用,当你的属性改变时,调用NotifyPropertyChanged("yourproperty")。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接