1

(There are similar questions around this topic, but none really match the way I've gone about it.)

I would like to change the colour of each of my DataGrid's cells based on their value inside them (an integer, from 0 to 3). Currently, I am able to change a cell's colour by mousing over, using this:

        <DataGrid Name="mapDisplay" ItemsSource="{Binding}" Margin="0,59,10,0">
            <DataGrid.CellStyle>
                <Style TargetType="DataGridCell">
                    <Style.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter Property="Background" Value="Red" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </DataGrid.CellStyle>
        </DataGrid>

This code changes any moused over cell to 'Red'. But how could I change the colour according to its value?

PL200
  • 741
  • 6
  • 24

2 Answers2

4

Please refer Change DataGrid cell colour based on values this answer.

I tried the same way which described in the answer with following code and its works fine.

<Window.Resources>        
        <local:ColorConverter x:Key="NameToBrushConverter"/>
 </Window.Resources>

    <Grid>
        <DataGrid ItemsSource="{Binding SampleList}"  AutoGenerateColumns="False">
            <DataGrid.Columns>
                <!-- Inputs -->
                <DataGridTextColumn Width="SizeToCells" Header="Inputs" MinWidth="100" Binding="{Binding RowNum}" >                  

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

                </DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>

Convertor Code:

public class ColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var input = int.Parse(value.ToString());
            switch (input)
            {
                case 1:
                    return Brushes.LightGreen;
                case 2:
                    return Brushes.LightBlue;
                case 3:
                    return Brushes.Yellow;
                default:
                    return DependencyProperty.UnsetValue;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

Hope this helps.

Community
  • 1
  • 1
Pabdev
  • 406
  • 3
  • 14
1

If your value-range is finite, you can do it in XAML using below apparoach. Below code assumes your property name is Status : int, and you want to change only the containing cell,and not entire row. Instead of DisplayIndex, you can Header property too to use Column name.

  <DataGrid x:Name="Dgrd">
        <DataGrid.CellStyle>
            <Style TargetType="DataGridCell">
                <Style.Triggers>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Status}" Value="0"/>
                            <Condition Binding="{Binding Column.DisplayIndex,RelativeSource={RelativeSource Self}}" Value="1"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Background" Value="Blue"/>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Status}" Value="1"/>
                            <Condition Binding="{Binding Column.DisplayIndex,RelativeSource={RelativeSource Self}}" Value="1"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Background" Value="Red"/>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Status}" Value="2"/>
                            <Condition Binding="{Binding Column.DisplayIndex,RelativeSource={RelativeSource Self}}" Value="1"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Background" Value="Yellow"/>
                    </MultiDataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Status}" Value="3"/>
                            <Condition Binding="{Binding Column.DisplayIndex,RelativeSource={RelativeSource Self}}" Value="1"/>
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Background" Value="Olive"/>
                    </MultiDataTrigger>
                </Style.Triggers>
            </Style>
        </DataGrid.CellStyle>
    </DataGrid>

You can also use a Converter.

AnjumSKhan
  • 9,647
  • 1
  • 26
  • 38
  • Your approach didn't seem to work for me entirely. However I did use this part to bind by DataTriger:`Column.DisplayIndex,RelativeSource={RelativeSource Self}` This seems to select the entire Column of the result with the correct value and changes the background, which is closer that I was before. Is it possible to make it only change the background for the Cells with the correct value? – PL200 Sep 17 '16 at 08:19
  • @PL200 It is currently changing only one cell, not entire column / row. – AnjumSKhan Sep 17 '16 at 10:20
  • So 'Status' would be the column header, yes? Is there a way to do this for all columns? – PL200 Sep 18 '16 at 10:50
  • @PL200 Instead of `Column.DisplayIndex` use `Column.Header` and use Status as `Value` to compare. – AnjumSKhan Sep 18 '16 at 15:50