Reputation: 73
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
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