【问题标题】:Change DataGrid cell colour based on values根据值更改 DataGrid 单元格颜色
【发布时间】:2011-07-29 19:24:15
【问题描述】:

我有一个 WPF 数据网格,我想要根据值使用不同的单元格颜色。我的 xaml 上有以下代码

Style TargetType="DataGridCell"

但不是只选择一个单元格而是选择所有行?我错过了什么?

【问题讨论】:

  • 您能否发布适用于您的场景的示例代码。这会有所帮助。顺便说一句,一种方法是将 datagridcell 的背景属性与该单元格的值绑定并使用转换器(从值转换为颜色)。

标签: c# wpf xaml colors datagrid


【解决方案1】:
 <DataGridTextColumn  Binding="{Binding Name}" Header="Name" Foreground="White">
     <DataGridTextColumn.CellStyle>
      <Style TargetType="{x:Type DataGridCell}">
         <Setter Property="Background" Value="{Binding color}" />
      </Style>
     </DataGridTextColumn.CellStyle>
 </DataGridTextColumn>

在 xaml.cs 文件中

SolidColorBrush color=new SolidColorBrush(Colors.Red);

【讨论】:

    【解决方案2】:

    如果您尝试设置DataGrid.CellStyle,DataContext 将是行,因此如果您想根据一个单元格更改颜色,那么在特定列中这样做可能是最简单的,特别是因为列可以有不同的内容,像文本块、组合框和复选框。这是将NameJohn 的所有单元格设置为浅绿色的示例:

    <DataGridTextColumn Binding="{Binding Name}">
        <DataGridTextColumn.ElementStyle>
            <Style TargetType="{x:Type TextBlock}">
                <Style.Triggers>
                    <Trigger Property="Text" Value="John">
                        <Setter Property="Background" Value="LightGreen"/>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </DataGridTextColumn.ElementStyle>
    </DataGridTextColumn>
    


    您也可以使用ValueConverter 来更改颜色。

    public class NameToBrushConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string input = (string)value;
            switch (input)
            {
                case "John":
                    return Brushes.LightGreen;
                default:
                    return DependencyProperty.UnsetValue;
            }
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }
    

    用法:

    <Window.Resources>
        <local:NameToBrushConverter x:Key="NameToBrushConverter"/>
    </Window.Resources>
    ...
    <DataGridTextColumn Binding="{Binding Name}">
        <DataGridTextColumn.ElementStyle>
            <Style TargetType="{x:Type TextBlock}">
                <Setter Property="Background" Value="{Binding Name, Converter={StaticResource NameToBrushConverter}}"/>
            </Style>
        </DataGridTextColumn.ElementStyle>
    </DataGridTextColumn>
    

    另一种选择是将Background 直接绑定到返回相应颜色画笔的属性。您必须在颜色所依赖的属性的设置器中触发属性更改通知。

    例如

    public string Name
    {
        get { return _name; }
        set
        {
            if (_name != value)
            {
                _name = value;
                OnPropertyChanged(nameof(Name));
                OnPropertyChanged(nameof(NameBrush));
            }
        }
    }
    
    public Brush NameBrush
    {
        get
        {
            switch (Name)
            {
                case "John":
                    return Brushes.LightGreen;
                default:
                    break;
            }
    
            return Brushes.Transparent;
        }
    }
    

    【讨论】:

    • 嗨 HB,谢谢它或多或少是我想要的,单元格改变但想根据值改变,必须查看值转换器并连接你发送给我的这个代码示例,但我认为这是正确的方向,你有我所说的任何例子吗?谢谢你
    • 我现在可以根据单元格的值获得浅绿色,但想使用值转换器来实现,我不想定义 value="john" 希望被触发并根据条件设置颜色我将以编程方式设置(cs.file c#),希望我能说清楚。非常感谢你帮助我
    • 关于 SO 的大量问题说明了如何使用值转换器,您真的可以进行一些搜索。编辑了我的答案以显示等效值转换器。
    • 我已经做到了,我确实已经实现了一个 claa,但它不能正常工作,这就是为什么问你,** namespace GridCellColor { public class MyValueConverter : IValueConverter { #region IValueConverter Members object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture){ if (Convert.ToInt32(value) &gt; 0) return 10; else if (Convert.ToInt32(value) == 0) return 0; else return -1; } 但不能正常工作为什么我问你是否有任何例子谢谢为您的回复
    • 该类将您的输入整数转换为另一个整数,这应该如何为背景着色?您需要一个返回 Brush 的转换器。
    【解决方案3】:

    基于“Cassio Borghi”的回答。使用这种方法,根本不需要更改 XAML。

            DataGridTextColumn colNameStatus2 = new DataGridTextColumn();
            colNameStatus2.Header = "Status";
            colNameStatus2.MinWidth = 100;
            colNameStatus2.Binding = new Binding("Status");
            grdComputer_Servives.Columns.Add(colNameStatus2);
    
            Style style = new Style(typeof(TextBlock));
            Trigger running = new Trigger() { Property = TextBlock.TextProperty, Value = "Running" };
            Trigger stopped = new Trigger() { Property = TextBlock.TextProperty, Value = "Stopped" };
    
            stopped.Setters.Add(new Setter() { Property = TextBlock.BackgroundProperty, Value = Brushes.Blue });
            running.Setters.Add(new Setter() { Property = TextBlock.BackgroundProperty, Value = Brushes.Green });
    
            style.Triggers.Add(running);
            style.Triggers.Add(stopped);
    
            colNameStatus2.ElementStyle = style;
    
            foreach (var Service in computerResult)
            {
                var RowName = Service;  
                grdComputer_Servives.Items.Add(RowName);
            }
    

    【讨论】:

      【解决方案4】:

      这可能对您有所帮助。然而,它不是普通的 WPF 数据网格。

      我使用带有自定义 ColorFormatter 行为的 DevExpress。我在市场上找不到任何开箱即用的产品。这花了我几天的时间来开发。我的代码附在下面,希望这对那里的人有所帮助。

      编辑:我使用了 POCO 视图模型和 MVVM,但是您可以根据需要将其更改为不使用 POCO。

      Viewmodel.cs

      namespace ViewModel
      {
          [POCOViewModel]
          public class Table2DViewModel
          {
              public ITable2DView Table2DView { get; set; }
      
              public DataTable ItemsTable { get; set; }
      
      
              public Table2DViewModel()
              {
              }
      
              public Table2DViewModel(MainViewModel mainViewModel, ITable2DView table2DView) : base(mainViewModel)
              {
                  Table2DView = table2DView;   
                  CreateTable();
              }
      
              private void CreateTable()
              {
                  var dt = new DataTable();
                  var xAxisStrings = new string[]{"X1","X2","X3"};
                  var yAxisStrings = new string[]{"Y1","Y2","Y3"};
      
                  //TODO determine your min, max number for your colours
                  var minValue = 0;
                  var maxValue = 100;
                  Table2DView.SetColorFormatter(minValue,maxValue, null);
      
                  //Add the columns
                  dt.Columns.Add(" ", typeof(string));
                  foreach (var x in xAxisStrings) dt.Columns.Add(x, typeof(double));
      
                  //Add all the values
                  double z = 0;
                  for (var y = 0; y < yAxisStrings.Length; y++)
                  {
                      var dr = dt.NewRow();
                      dr[" "] = yAxisStrings[y];
                      for (var x = 0; x < xAxisStrings.Length; x++)
                      {
                          //TODO put your actual values here!
                          dr[xAxisStrings[x]] = z++; //Add a random values
                      }
                      dt.Rows.Add(dr);
                  }
                  ItemsTable = dt;
              }
      
      
              public static Table2DViewModel Create(MainViewModel mainViewModel, ITable2DView table2DView)
              {
                  var factory = ViewModelSource.Factory((MainViewModel mainVm, ITable2DView view) => new Table2DViewModel(mainVm, view));
                  return factory(mainViewModel, table2DView);
              }
          }
      
      }
      

      IView.cs

      namespace Interfaces
          {
              public interface ITable2DView
              {
                  void SetColorFormatter(float minValue, float maxValue, ColorScaleFormat colorScaleFormat);
              }
          }
      

      View.xaml.cs

      namespace View
      {
          public partial class Table2DView : ITable2DView
          {
              public Table2DView()
              {
                  InitializeComponent();
              }
      
              static ColorScaleFormat defaultColorScaleFormat = new ColorScaleFormat
              {
                  ColorMin = (Color)ColorConverter.ConvertFromString("#FFF8696B"),
                  ColorMiddle = (Color)ColorConverter.ConvertFromString("#FFFFEB84"),
                  ColorMax = (Color)ColorConverter.ConvertFromString("#FF63BE7B")
              };
      
              public void SetColorFormatter(float minValue, float maxValue, ColorScaleFormat colorScaleFormat = null)
              {
                  if (colorScaleFormat == null) colorScaleFormat = defaultColorScaleFormat;
                  ConditionBehavior.MinValue = minValue;
                  ConditionBehavior.MaxValue = maxValue;
                  ConditionBehavior.ColorScaleFormat = colorScaleFormat;
              }
          }
      }
      

      DynamicConditionBehavior.cs

      namespace Behaviors
      {
          public class DynamicConditionBehavior : Behavior<GridControl>
          {
              GridControl Grid => AssociatedObject;
      
              protected override void OnAttached()
              {
                  base.OnAttached();
                  Grid.ItemsSourceChanged += OnItemsSourceChanged;
              }
      
              protected override void OnDetaching()
              {
                  Grid.ItemsSourceChanged -= OnItemsSourceChanged;
                  base.OnDetaching();
              }
      
              public ColorScaleFormat ColorScaleFormat { get; set;}
              public float MinValue { get; set; }
              public float MaxValue { get; set; }
      
              private void OnItemsSourceChanged(object sender, EventArgs e)
              {
                  var view = Grid.View as TableView;
      
                  if (view == null) return;
      
                  view.FormatConditions.Clear();
      
                  foreach (var col in Grid.Columns)
                  {
                      view.FormatConditions.Add(new ColorScaleFormatCondition
                      {
                          MinValue = MinValue,
                          MaxValue = MaxValue,
                          FieldName = col.FieldName,
                          Format = ColorScaleFormat,
                      });
                  }
      
              }
          }
      }
      

      View.xaml

      <UserControl x:Class="View"
                   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                   xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                   xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" 
                   xmlns:ViewModels="clr-namespace:ViewModel"
                   xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
                   xmlns:behaviors="clr-namespace:Behaviors"
                   xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking"
                   DataContext="{dxmvvm:ViewModelSource Type={x:Type ViewModels:ViewModel}}"
                   mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="800">
      
          <UserControl.Resources>
              <Style TargetType="{x:Type dxg:GridColumn}">
                  <Setter Property="Width" Value="50"/>
                  <Setter Property="HorizontalHeaderContentAlignment" Value="Center"/>
              </Style>
      
              <Style TargetType="{x:Type dxg:HeaderItemsControl}">
                  <Setter Property="FontWeight" Value="DemiBold"/>
              </Style>
          </UserControl.Resources>
      
              <!--<dxmvvm:Interaction.Behaviors>
                  <dxmvvm:EventToCommand EventName="" Command="{Binding OnLoadedCommand}"/>
              </dxmvvm:Interaction.Behaviors>-->
              <dxg:GridControl ItemsSource="{Binding ItemsTable}"
                           AutoGenerateColumns="AddNew"
                           EnableSmartColumnsGeneration="True">
      
              <dxmvvm:Interaction.Behaviors >
                  <behaviors:DynamicConditionBehavior x:Name="ConditionBehavior" />
                  </dxmvvm:Interaction.Behaviors>
                  <dxg:GridControl.View>
                      <dxg:TableView ShowGroupPanel="False"
                                 AllowPerPixelScrolling="True"/>
                  </dxg:GridControl.View>
              </dxg:GridControl>
        </UserControl>
      

      【讨论】:

        【解决方案5】:

        在我的情况下转换器必须返回字符串值。我不知道为什么,但它有效。

        *.xaml(通用样式文件,包含在另一个xaml文件中)

        <Style TargetType="DataGridCell">
                <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource ValueToBrushConverter}}" />
        </Style>
        

        *.cs

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            Color color = VSColorTheme.GetThemedColor(EnvironmentColors.ToolWindowBackgroundColorKey);
            return "#" + color.Name;
        }
        

        【讨论】:

          【解决方案6】:

          如果您需要使用一定数量的列来执行此操作,那么 H.B. 的方式是最好的。但是,如果您在运行时之前不知道要处理多少列,那么下面的代码 [re​​ad: hack] 将起作用。我不确定是否有更好的解决方案,列数未知。我断断续续地花了两天时间才得到它,所以无论如何我都会坚持下去。

          C#

          public class ValueToBrushConverter : IValueConverter
          {
              public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
              {
                  int input;
                  try
                  {
                      DataGridCell dgc = (DataGridCell)value;
                      System.Data.DataRowView rowView = (System.Data.DataRowView)dgc.DataContext;
                      input = (int)rowView.Row.ItemArray[dgc.Column.DisplayIndex];
                  }
                  catch (InvalidCastException e)
                  {
                      return DependencyProperty.UnsetValue;
                  }
                  switch (input)
                  {
                      case 1: return Brushes.Red;
                      case 2: return Brushes.White;
                      case 3: return Brushes.Blue;
                      default: return DependencyProperty.UnsetValue;
                  }
              }
          
              public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
              {
                  throw new NotSupportedException();
              }
          }
          

          XAML

          <UserControl.Resources>
              <conv:ValueToBrushConverter x:Key="ValueToBrushConverter"/>
              <Style x:Key="CellStyle" TargetType="DataGridCell">
                  <Setter Property="Background" Value="{Binding RelativeSource={RelativeSource Self}, Converter={StaticResource ValueToBrushConverter}}" />
              </Style>
          </UserControl.Resources>
          <DataGrid x:Name="dataGrid" CellStyle="{StaticResource CellStyle}">
          </DataGrid>
          

          【讨论】:

          • Brushes.Red 没有帮助,但 "#" + color.Name 是。想法肯定是你的。谢谢
          【解决方案7】:
                  // Example: Adding a converter to a column (C#)
                  Style styleReading = new Style(typeof(TextBlock));
                  Setter s = new Setter();
                  s.Property = TextBlock.ForegroundProperty;
                  Binding b = new Binding();
                  b.RelativeSource = RelativeSource.Self;
                  b.Path = new PropertyPath(TextBlock.TextProperty);
                  b.Converter = new ReadingForegroundSetter();
                  s.Value = b;
                  styleReading.Setters.Add(s);
                  col.ElementStyle = styleReading;
          

          【讨论】:

          【解决方案8】:

          在后面的代码 (VB.NET) 中执行此操作

          Dim txtCol As New DataGridTextColumn
          
          Dim style As New Style(GetType(TextBlock))
          Dim tri As New Trigger With {.Property = TextBlock.TextProperty, .Value = "John"}
          tri.Setters.Add(New Setter With {.Property = TextBlock.BackgroundProperty, .Value = Brushes.Green})
          style.Triggers.Add(tri)
          
          xtCol.ElementStyle = style
          

          【讨论】:

            【解决方案9】:

            换个方式

            <Style TargetType="{x:DataGridCell}" >
            

            但请注意,这将针对您的所有单元格(您针对的是 DataGridCell 类型的所有对象) 如果您想根据单元格类型设置样式,我建议您使用DataTemplateSelector

            可以在 Christian Mosers 的 DataGrid 教程中找到一个很好的示例:

            http://www.wpftutorial.net/DataGrid.html#rowDetails

            玩得开心:)

            【讨论】:

            • 嗨大马士革,感谢您的回复,我有 DatagridCell 的 TargetType,您是对的,因为它影响了我的整个行。我希望只影响一个单元格,具体取决于该单元格的值。我该怎么做?
            • 其实这取决于你的情况。你看到我给你的链接上的例子了吗?关于如何根据对象类型(在示例中:男孩或女孩)选择样式有一个非常清楚的示例。你的问题是否类似?
            • 不,它不相似,因为我希望选择一个单元格而不是整个行,因为它是在示例中播种的。
            猜你喜欢
            • 2020-06-02
            • 1970-01-01
            • 2014-03-12
            • 2011-08-13
            • 2021-04-06
            • 2017-08-23
            • 1970-01-01
            相关资源
            最近更新 更多