Turns out it's surprisingly hard to bubble up property changes from items inside an ObservableCollection - by default it only raises changed events when the collection itself is modified, not the items within it.
This SO answer (to another of my questions on the subject) suggested that one way round the problem was to use a converter:
WPF MVVM - Datagrid does not update changed properties of child items
And for one of my scenarios, where the style of an item is dependent on its value and that value can be changed via the user editing the DataGrid, it works beautifully.
However, in the same DataGrid it's possible to update another field by pressing a button - the button is in the same ViewModel, but it doesn't belong to the datagrid itself. I tried a similar trick to get this to work:
<DataGridTextColumn Header="Status" Binding="{Binding Status}" IsReadOnly="True">
<DataGridTextColumn.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Background">
<Setter.Value>
<Binding Converter="{StaticResource BookingBackgroundConverter}" />
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
And the converter:
public class BookingBackgroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
Booking b = (Booking)value;
switch(b.Status)
{
case "Booking" :
return Brushes.LightBlue;
case "Booked" :
return Brushes.LightGreen;
default :
return Brushes.Transparent;
}
}
public object ConvertBack(object value, Type TargetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
Incidentally I was surprised that the value going into the Converter turned out to be a Booking - that's what the row is bound to, not the *column - I was expecting to get the string value of Status. Might be useful to know why that is, as it may have a bearing on the answer.
Anyway, here's the button click command that changes the Status:
private void BookCount()
{
SelectedBooking.Status = "Booking";
rep.SaveChanges();
OnPropertyChanged("");
}
SelectedBooking is a property that holds the currently selected row. And I'm firing an empty OnPropertyChanged in desperation to try and get this to update.
But no joy - the converter code doesn't get hit until the View reloads. Why does the converter approach work for datagrid edits but not button clicks, and what can I do to get the button click to visually update the status column?