Change the color of a DataGrid cell based on values

I have a datagrid WPF and I want the different cell colors to match the values. I have code on my xaml

Style TargetType="DataGridCell" 

but instead of selecting a cell, only the row is selected? What am I missing?

+60
c # colors wpf xaml datagrid
Apr 05 2018-11-11T00:
source share
8 answers

If you try to set DataGrid.CellStyle , then the DataContext will be a row, so if you want to change the color based on one cell, this can be easiest done in certain columns, especially since the columns can have different contents, such as TextBlocks, ComboBoxes and checkboxes. Here is an example of setting all the green cells, where Name is John :

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

A screenshots




You can also use ValueConverter to change the color.

 public class NameToBrushConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { string input = value as string; 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(); } } 

Using:

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



Another option is to directly bind Background to a property that returns a color brush accordingly. You will have to activate property change notifications in the property settings on which the color depends.

eg.

 public string Name { get { return _name; } set { if (_name != value) { _name = value; OnPropertyChanged("Name"); OnPropertyChanged("NameBrush"); } } } public Brush NameBrush { get { switch (Name) { case "John": return Brushes.LightGreen; default: break; } return Brushes.Transparent; } } 
+129
Apr 05 2018-11-12T00:
source share

If you need to do this with a given number of columns, HB is the best way. But if you don’t know how many columns you have in mind before executing, then the following code [read: hack] will work. I am not sure if there is a better solution with an unknown number of columns. It took me two days to work on this to get it, so I stick to it independently.

FROM#

 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> 
+15
Jul 12 '13 at 17:10
source share

Just put instead

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

But be careful that this will target ALL of your cells (you are targeting all objects of type DataGridCell ) If you want to style your cell type, I would recommend that you use DataTemplateSelector

A good example can be found in Christian Moser's DataGrid tutorial:

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

Good luck :)

+2
Apr 05 2018-11-11T00:
source share

In my case, the converter should return a string value. I don’t know why, but it works.

*. xaml (a common style file that is included in other xaml files)

 <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; } 
+2
Sep 29 '16 at 11:27
source share

It can help you. However, this is not a stock WPat datagrid.

I used DevExpress with custom ColorFormatter behavior. I could not find anything in the market that made it out of the box. It took me a few days to develop. My code is below, hope this helps someone out there.

Edit: I used the POCO and MVVM view models, but you can change this to not use POCO if you want.

Example

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> 
+2
Nov 19 '16 at 0:35
source share
  // 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; 
+1
Jan 27 '13 at 9:34 on
source share

Based on Cassio Borgi's answer. When using this method, there is no need to change XAML at all.

  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); } 
0
May 17 '19 at 1:45
source share

To do this in the code behind (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 
-one
Aug 09 2018-12-12T00:
source share



All Articles