EASameh
EASameh

Reputation: 73

WPF datagrid change row color based on a property value

I have a WPF Datagrid that is filled with a CollectionViewSource and what I want is to change the row background color depending on a binded property value.

I've read different threads here on SO such as Change Data bound WPF Datagrid row background/foreground color depending on the boolean property of an object or WPF Datagrid row colour based on value but still struggling to make this work.

I don't know what is wrong with my code. Here is what I tried:

Main.Xaml

<UserControl.DataContext>
        <Viewmodel:LoadServerViewModel/>
</UserControl.DataContext>

<Grid Margin="10,20,20,20" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="6">
    <DataGrid AutoGenerateColumns="False" 
              ScrollViewer.CanContentScroll="True" 
              ScrollViewer.VerticalScrollBarVisibility="Visible" 
              ScrollViewer.HorizontalScrollBarVisibility="Visible" 
              VerticalAlignment="Stretch"
              IsReadOnly="False" 
              ItemsSource="{Binding Servers}">
        <DataGrid.RowStyle>
            <Style TargetType="DataGridRow">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding RowStatus}" Value="Created">
                        <Setter Property="Background" Value="Yellow" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding RowStatus}" Value="OK">
                        <Setter Property="Background" Value="Green" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding RowStatus}" Value="KO">
                        <Setter Property="Background" Value="Red" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGrid.RowStyle>
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
            <DataGridTextColumn Header="Last Update" Binding="{Binding LastUp} />
            ....
        </DataGrid.Columns>
    </DataGrid>
</Grid>

<Button Style="{DynamicResource RoundedButtonStyle}" Grid.Row="1" Grid.Column="3"
                Content="Refresh"
                Margin="0,0,40,0"
                Height="25"
                Width="90"
                Foreground="#FFFFFF"
                Background="#2f3640"
                Command="{Binding ButtonRefresh}">
</Button>

LoadServerViewModel.cs

private string _rowStatus = "Created";
private readonly RelayCommand _buttonRefresh;

public string RowStatus
{
    get => _rowStatus;
    set
    {
        _rowStatus = value;
        OnPropertyChanged(nameof(RowStatus));
    }
}

public ICollectionView Servers
{
    get
    {
        if (_collectionViewSource.View != null)
        {
            _collectionViewSource.View.CurrentChanged += (sender, e) => ServerGridFormat = _collectionViewSource.View.CurrentItem as ServerGridFormat;
            return _collectionViewSource?.View;
        }
        return null;
    }
}

public ServerGridFormat ServerGridFormat 
{
    get => _servergridformat;
    set
    {
        servergridformat = value;
        OnPropertyChanged(nameof(ServerGridFormat));
    }
}

public LoadServerViewModel() {
    // Button to trigger the change of RowStatus from "Created" to "OK" therefore the color of all rows
    _buttonRefresh = new RelayCommand(o => RowStatus = "OK");
}

Thanks for your help

Upvotes: 2

Views: 2788

Answers (1)

BionicCode
BionicCode

Reputation: 28948

You current binding uses the DataContext of the individual row as binding source (which is the data model stored in the ItemsSource). But your property RowStatus is defined on the object that is the DataContext of the DataGrid (which is the LoadServerViewModel).

To make it work, you must adjust your data bindings to use the correct source (or alternatively move the RowSatus property to the data models):

<Style TargetType="DataGridRow">
  <Style.Triggers>
    <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=DataGrid}, Path=DataContext.RowStatus}" 
                 Value="Created">
      <Setter Property="Background" Value="Yellow" />
    </DataTrigger>
  </Style.Triggers>
</Style>

Upvotes: 3

Related Questions