I have WPF Application that contains a DataGrid
, which is bound onto a C# DataTable
.
It has a converter that changes the background-color of the cell based on the value inside the cell.
Under normal use everything works as it's supposed to, but when I update the values of the DataTable from a seperate Thread, the displayed value changes, but the converter isn't triggered.
The DataGrid:
<UserControl.Resources>
<utility:CellColorConverter x:Key="ColorConverter" />
<Style x:Key="BlueDataGridStyle" TargetType="{x:Type DataGrid}">
<Setter Property="CellStyle" Value="{DynamicResource BlueDataGridCellStyle}" />
</Style>
<Style x:Key="BlueDataGridCellStyle" TargetType="DataGridCell" >
<Setter Property="Background">
<Setter.Value>
<MultiBinding Converter="{StaticResource ColorConverter}">
<MultiBinding.Bindings>
<Binding RelativeSource="{RelativeSource Self}" />
<Binding Path="Row" />
</MultiBinding.Bindings>
</MultiBinding>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<DataGrid
Name="dgSimple"
AutoGenerateColumns="True"
ItemsSource="{Binding Grid}"
IsReadOnly="True"
CanUserResizeColumns="False"
CanUserResizeRows="False"
CanUserSortColumns="False"
CanUserReorderColumns="False"
Margin="6"
SelectedIndex="{Binding SelectedRow}"
CurrentColumn="{Binding SelectedColumn}"
Style="{StaticResource BlueDataGridStyle}"
HeadersVisibility="All"
RowHeaderWidth="32"
ColumnWidth="32">
</DataGrid>
The Converter:
public class CellColorConverter : IMultiValueConverter
{
object IMultiValueConverter.Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values[0] is DataGridCell cell && values[1] is DataRow row)
{
try
{
string columnName = (string)cell.Column.Header;
int columnIndex = cell.Column.DisplayIndex;
if (columnIndex == 0)
{
cell.FontStyle = FontStyles.Italic;
cell.FontWeight = FontWeights.Bold;
cell.FontSize = 20;
return new SolidColorBrush(Colors.Yellow);
}
string content = row.Field<string>(columnName); // Header must be same as column name
if (content == "w")
{
return new SolidColorBrush(Colors.Blue);
}
if (content == "h")
{
return new SolidColorBrush(Colors.Red);
}
if (content == "m")
{
return new SolidColorBrush(Colors.LightGray);
}
if (content == "c" || content == "b" || content == "s" || content == "d" || content == "p")
{
return new SolidColorBrush(Colors.Gray);
}
}
catch (Exception e)
{
Debug.WriteLine(e);
return new SolidColorBrush(Colors.Black); // Error! An Exception was thrown
}
}
return new SolidColorBrush(Colors.Green); // Something else.
}
object[] IMultiValueConverter.ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotSupportedException();
}
}
I tried invoking the NotifyPropertyChanged event, in hopes that that would trigger the converter, but had no luck with that.
I would assume the issue is that you are not invoking the setter using the Dispatcher. I don't see the code that you fire under a different thread, but I would add code like this:
//code fired on non UI thread.
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
//call code will trigger PropertyChanged event
}));