Cambiar el color de la celda de DataGrid según los valores

Tengo una cuadrícula de datos WPF y quiero colores de celda diferentes según los valores. Tengo el código de abajo en mi xaml

Style TargetType="DataGridCell" 

pero en lugar de seleccionar una celda, ¿solo está seleccionando toda la fila? ¿Qué me estoy perdiendo?

Si intentas configurar DataGrid.CellStyle DataContext será la fila, por lo que si deseas cambiar el color según una celda, es más fácil hacerlo en columnas específicas, especialmente porque las columnas pueden tener contenidos variables, como TextBlocks, ComboBoxes y CheckBoxes. Aquí hay un ejemplo de establecer todas las celdas de color verde claro donde el Name es John :

      

Una captura de pantalla


También podría usar un ValueConverter para cambiar el 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(); } } 

Uso:

    ...      

Otra opción más es vincular directamente el Background a una propiedad que devuelve el pincel respectivamente de color. Tendrá que disparar las notificaciones de cambio de propiedad en los ajustadores de propiedades de las que depende el color.

p.ej

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

Si necesita hacerlo con un número determinado de columnas, el camino de HB es el mejor. Pero si no sabe cuántas columnas está tratando hasta el tiempo de ejecución, entonces el siguiente código [leer: hackear] funcionará. No estoy seguro de si hay una solución mejor con un número desconocido de columnas. Me tomó dos días trabajar en eso para obtenerlo, así que me estoy quedando con eso independientemente.

DO#

 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

       

Solo ponlo en su lugar

  

Pero tenga en cuenta que esto se dirigirá a TODAS sus celdas (apuntará a todos los objetos de tipo DataGridCell ). Si desea poner un estilo de acuerdo con el tipo de celda, le recomendaría que use un DataTemplateSelector

Un buen ejemplo se puede encontrar en el tutorial DataGrid de Christian Mosers:

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

Que te diviertas 🙂

En mi caso, el convertidor debe devolver el valor de la cadena. No sé por qué, pero funciona.

* .xaml (archivo de estilo común, que está incluido en otros archivos xaml)

  

* .cs

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

Esto puede ser de ayuda para usted. Sin embargo, no es la cuadrícula de datos WPF de valores.

Utilicé DevExpress con un comportamiento ColorFormatter personalizado. No pude encontrar nada en el mercado que hiciera esto de la caja. Esto me llevó unos días en desarrollarme. Mi código se adjuntó a continuación, con suerte, esto ayuda a alguien por ahí.

Editar: utilicé los modelos POCO view y MVVM; sin embargo, puede cambiar esto para no usar POCO si lo desea.

Ejemplo

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

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

Para hacer esto en el código detrás (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