Search code examples
c#wpfdatagridwpf-style

How to set the background color of a data grid row using a viewmodel value and a lookup dictionary?


I have a DataGrid where I set ItemsSource as such:

TheGrid.ItemsSource = items;

And a XAML:

<DataGrid Name="TheGrid" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False">
  <DataGrid.Resources>
    <Style.Setters>
      <Setter Property = "Background" Value="{Binding = ???}" ></Setter>
    </Style.Setters>
  </DataGrid.Resources>
  <DataGrid.Columns>
    <DataGridTextColumn Header="Id" Binding="{Binding Id}"/>
    <DataGridTextColumn Header="Time" Binding="{Binding Time}"/>
    ...
  </DataGrid.Columns>
</DataGrid>

Now, in my view, I have a public dictionary as such:

public IDictionary<string, Color> IdColors { get; set; }

The issue is I do not know how to take the Id from my ItemsSource and pass it into the binding such that it would access the dictionary on that id and take the color. I have read alternative solutions,such as:

  1. Doing this in a converter

  2. Subscribing to LoadingRow and just setting it there programmatically

I think I know how to do #2 but I've come to ask stack whether that would be advisable.


Solution

  • If you want to define a converter, you can do it this way:

    public class IdToBrushConverter : IValueConverter {
        /// <summary>
        /// Converts an ID into a Brush
        /// </summary>
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
            return new SolidColorBrush(IdColors[value]); //need for example some static access to IdColors here
            //You can also define IdColors here or use other custom logic.
        }
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
            throw new NotImplementedException();
        }
    }
    

    And in your XAML, you can call the converter like this:

    <DataGrid Name="TheGrid" AutoGenerateColumns="False" CanUserAddRows="False CanUserDeleteRows="False">
      <DataGrid.Resources>
        <!--You might need some namespace prefix here-->
        <view:IdToBrushConverter x:Key="IdToBrushConverter"></view:IdToBrushConverter>
        <Style.Setters>
          <Setter Property = "Background" Value="{Binding Path=Id, Converter={StaticResource IdToBrushConverter}" ></Setter>
        </Style.Setters>
      </DataGrid.Resources>
      <DataGrid.Columns>
        <DataGridTextColumn Header="Id" Binding="{Binding Id}"/>
        <DataGridTextColumn Header="Time" Binding="{Binding Time}"/>
        ...
      </DataGrid.Columns>
    </DataGrid>
    

    The converter will be called and applied to the Id property and return a SolidColorBrush with the color you want.