0

I have an ObservableCollection TableRows of this struct binded to a DataGrid:

public class TableStruct
{
    public string Item1 {get; set;}
    public string Item2 {get; set;}
    public string Item3 {get; set;}
    public string Item4 {get; set;}
    public string Item5 {get; set;}
    public string Item6 {get; set;}
}

When trying to update individual items in a row, I tried doing it like this:

for(int i = 0; i < TableRows.Count; i++)
{
    if(SomeConditional)
    {
        TableStruct new_row = TableRows[i];
        new_row.Item3 = "changed";
        TableRows[i] = new_row;
    }
}

But when running the program the DataGrid is not updated. however running this code does update to the DataGrid and works as intended:

for(int i = 0; i < TableRows.Count; i++)
{
    if(SomeConditional)
    {
        TableStruct new_row = new TableStruct();
        new_row.Item1 = "same";
        new_row.Item2 = "same";
        new_row.Item3 = "changed";
        new_row.Item4 = "same";
        new_row.Item5 = "same";
        new_row.Item6 = "same";
        TableRows[i] = new_row;
    }
}

What is different here? In my mind they both accomplish the same task but one takes more lines than the other.

burritab
  • 25
  • 4
  • 1
    `TableStruct` should implement [INotifyPropertyChanged](https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.inotifypropertychanged?view=netframework-4.8). – mm8 Jul 15 '19 at 14:03
  • obviously because ObservableCollection observes changes of itself not its elements – Selvin Jul 15 '19 at 14:03
  • Does your class, `TableStruct` implement [INotifyPropertyChanged](https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.inotifypropertychanged?view=netframework-4.8)? I think whats happening in your first example is that no change notifications are being sent. In the second example, you're actually replacing one of the items in `TableRows` which causes a change notification. – Joshua Robinson Jul 15 '19 at 14:04
  • The important difference is that the first case is effectivly `TableRows[i] = TableRows[i]` while the second is `TableRows[i] = new TableStruct()`. The first case is ignored by the ObservableCollection. – Clemens Jul 15 '19 at 14:05

1 Answers1

0

TableStruct should implement INotifyPropertyChanged:

public class TableStruct : INotifyPropertyChanged
{
    private string _item3;
    public string Item3
    {
        get { return _item3; }
        set { _item3 = value; NotifyPropertyChanged(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;  
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    //...
}

If you raise the PropertyChanged event by calling the NotifyPropertyChanged() method in all setters, you can set the properties of a TableStruct directly to update the UI:

for (int i = 0; i<TableRows.Count; i++)
{
    if (SomeConditional)
    {
        TableRows[i].Item3 = "changed";
    }
}

An ObservableCollection<T> doesn't notify the UI when a property of an item changes. It only notifies about items being added, removed or moved within the collection.

mm8
  • 163,881
  • 10
  • 57
  • 88