none
How to raise PropertyChanged event for item in ObservableCollection?

    Question

  • Hi!

    How can I achieve that an ObservableCollection<T> raises the PropertyChanged event if any property of T is changed?

    I assumed that this feature is built in into ObservableCollection<T>, because the documentation says:

    "To fully support transferring data values from binding source objects to binding targets, each object in your collection that supports bindable properties must implement an appropriate property changed notification mechanism such as the INotifyPropertyChanged interface."

    I implemented INotifyPropertyChanged on T, but it still does not work.

    Please find below the code I used; here "T" is the class "Person". When btnModifyProperty_Click() is called, Person.OnPropertyChanged() is called, but the PropertyChanged event of m_persons never is raised. (btnAddItem_Click(), however, works fine).

        public class Person : INotifyPropertyChanged  
        {  
            public event PropertyChangedEventHandler PropertyChanged;  
     
            public string Name  
            {  
                get { return m_Name; }  
                set { m_Name = value; OnPropertyChanged("Name"); }  
            }  
            string m_Name;  
     
            protected void OnPropertyChanged(string name)  
            {  
                if (PropertyChanged != null)  
                {  
                    PropertyChanged(thisnew PropertyChangedEventArgs(name));  
                }  
            }  
        }  
     
        public partial class Window1 : Window  
        {  
            ObservableCollection<Person> m_persons = new ObservableCollection<Person>{  
                    new Person { Name = "Andy" },  
                    new Person { Name = "David" },  
                    new Person { Name = "Jack" }  
                };  
     
            public Window1()  
            {  
                InitializeComponent();  
     
                m_persons.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(m_persons_CollectionChanged);  
                ((INotifyPropertyChanged)m_persons).PropertyChanged += new PropertyChangedEventHandler(Window1_PropertyChanged);  
            }  
     
            void Window1_PropertyChanged(object sender, PropertyChangedEventArgs e)  
            {  
                MessageBox.Show("PropertyChanged!");  
            }  
     
            void m_persons_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)  
            {  
                MessageBox.Show("CollectionChanged!");  
            }  
     
            private void btnModifyProperty_Click(object sender, RoutedEventArgs e)  
            {  
                m_persons[0].Name = "Joe";  
            }  
     
            private void btnAddItem_Click(object sender, RoutedEventArgs e)  
            {  
                m_persons.Add(new Person { Name = "John" });  
            }  
        } 

    Many thanks in advance for any help.

    Regards
    - Frank

    Friday, July 25, 2008 3:17 PM

Answers

  • Hi Frank,

    ObservableCollection<T> does implement INotifyPropertyChanged, however it only raises PropertyChanged events for changes in its own properties, not for the properties of the items which it contains.

    Therefore, you will find that PropertyChanged events occur when you add a new item to indicate that the Count property of the collection has changed.

    In order to for what you are trying to achieve, you should iterate over all the items within the collection, adding handlers for the PropertyChanged events from each item. You will also have to ensure that when items are added to the collection you add PropertyChanged event handlers for them also (by adding a handler for the CollectionChanged event).

    I cover some of this in my recent article on creating a pie chart with data binding, see section three:

    http://www.codeproject.com/KB/WPF/PieChartDataBinding.aspx#three


    Regards,
    Colin E.
    • Proposed as answer by Colin Eberhardt Friday, July 25, 2008 3:43 PM
    • Marked as answer by fmunkert Friday, July 25, 2008 7:22 PM
    Friday, July 25, 2008 3:43 PM

All replies

  • Hi Frank,

    ObservableCollection<T> does implement INotifyPropertyChanged, however it only raises PropertyChanged events for changes in its own properties, not for the properties of the items which it contains.

    Therefore, you will find that PropertyChanged events occur when you add a new item to indicate that the Count property of the collection has changed.

    In order to for what you are trying to achieve, you should iterate over all the items within the collection, adding handlers for the PropertyChanged events from each item. You will also have to ensure that when items are added to the collection you add PropertyChanged event handlers for them also (by adding a handler for the CollectionChanged event).

    I cover some of this in my recent article on creating a pie chart with data binding, see section three:

    http://www.codeproject.com/KB/WPF/PieChartDataBinding.aspx#three


    Regards,
    Colin E.
    • Proposed as answer by Colin Eberhardt Friday, July 25, 2008 3:43 PM
    • Marked as answer by fmunkert Friday, July 25, 2008 7:22 PM
    Friday, July 25, 2008 3:43 PM
  • Is isn't supposed to raise that event if properties on collection objects change. It's supposed to fire notifications about the membership of the collection changing, that's all. It is assumed that any consumer of the collection will bind to each item, so will then receive notifications from the items directly via INotifyPropertyChanged.

    edit: oops, didn't see Colin had already answered.


    Controls for WPF and Windows Forms at http://www.divelements.co.uk
    • Edited by Tim Dawson Friday, July 25, 2008 5:06 PM addtion
    Friday, July 25, 2008 5:05 PM
  • Hi Colin,
    Hi Tim,

    many thanks for your replies. I have adapted my code accordingly, and it works fine now.

    Regards
    - Frank
    Friday, July 25, 2008 7:23 PM
  • Hi Frank,

    I have the same problem, could you please explain how did you solved the problem. It will be good you can provide the code as well.


    Thanks in advance

    Regards
    - Vishal B
    Friday, January 08, 2010 12:56 PM