简体   繁体   中英

WPF - Value inside datagrid fails to update converter when changed externally

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?

You change Status but you bind whole Booking object which means it will trigger only when whole object changes and not when any property from within that object changes. Bind Status instead

<Binding Path=Status, Converter="{StaticResource BookingBackgroundConverter}" />

and change converter to work with your booking status instead of Booking object. If you need to pass multiple values use IMultiValueConverter with MultiBinding

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM