2

How can I trigger NotifyOfPropertyChange by changing property of item inside of ObservableCollection?

Currently I am assigning null to ObservableCollection and then the original value. However, I don't think this is a proper solution.

ObservableCollection<Item> temp = Collection;
Collection = null;
Collection = temp;

I have also tried to implement INotifyPropertyChanged interface, but it didn't work

public class Item : INotifyPropertyChanged
{
    public string Name { get; set; }

    public event PropertyChangedEventHandler? PropertyChanged;
}
Filip Zaťko
  • 33
  • 1
  • 1
  • 6
  • Does `Item` implement `INotifyPropertyChanged`? –  Mar 02 '23 at 21:34
  • 1
    I have tried to implement this interface but it didn't react. – Filip Zaťko Mar 02 '23 at 21:36
  • For the best chance of receiving help, post **everything** you tried. Your implementation of `INotifyPropertyChanged` in `Item` would be relevant to your question. –  Mar 02 '23 at 21:39

2 Answers2

0

Implementing INotifyPropertyChanged is not enough, you actually have to use it.

See INotifyPropertyChanged Interface documentation for an example.

using System.ComponentModel;
using System.Runtime.CompilerServices;

public class Item : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

    // This method is called by the Set accessor of each property.  
    // The CallerMemberName attribute that is applied to the optional propertyName  
    // parameter causes the property name of the caller to be substituted as an argument.  
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }


    private string m_name = "";

    public string Name
    {
        get
        {
            return m_name;
        }
        set
        {
            if (m_name != value)
            {
                m_name = value;
                NotifyPropertyChanged();
            }
        }
    }
}
0

Though the answer of @rshepp is a perfect point, it is not the whole story.

The ObservableCollection class is designed to enable feedback when items are added or removed from the collection. But if one of the items inside collection changes a value, your collection will not notice - unless the contained items implement the INotifyPropertyChanged interface and you attach to the event handler.

public class MotherClass
{
    public MotherClass()
    {
        MonitoredItems = new();

        MonitoredItems.CollectionChanged += MonitoredItems_CollectionChanged;
    }

    public ObservableCollection<Item> MonitoredItems { get; }

    private void MonitoredItems_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.OldItems is not null)
        {
            foreach (Item item in e.OldItems)
            {
                //Removed items
                item.PropertyChanged -= MonitoredItem_PropertyChanged;
            }
        }
        else if (e.NewItems is not null)
        {
            foreach (Item item in e.NewItems)
            {
                //Added items
                item.PropertyChanged += MonitoredItem_PropertyChanged;
            }
        }
    }

    private void MonitoredItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (sender is not Item sendingItem)
            return;
        Trace.WriteLine($"The {nameof(Item)} object with Name {sendingItem.Name} has a change in its property {e.PropertyName} ");
    }
}

Of course, you are free to extend this example MotherClass to MotherClass extending ObservableCollection, if you are able to contain the the sub-property changed event inside the collection.

Note there is no setter for the ObservableCollection to keep the attached event handler intact. The outside code can still use something like .Clear or .ReplaceRange to set brand new collection values.

ThomasB
  • 161
  • 6