5

I have a class that implements the INotifyPropertyChanged interface. Some of the properties of the class are of type List. For example:

public List<string> Answers
{
    get { return _answers;  }
    set
    {
      _answers = value;
      onPropertyChanged("Answers")
    }
}

...

private void onPropertyChanged(string propertyName)
{
    if(this.PropertyChanged != null)
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

If I assign a new List<string> to Answer, then the PropertyChanged event fires as expected; but if I add a string string to the Answer list using the List Add method, then PropertyChanged event doesn't fire.

I was considering adding an AddAnswer() method to my class, which would handle calling the lists's Add method and would call onPropertyChanged() from there, but is that the right way to do it? Is there a more elegant way of doing it?

Cheers, KT

eponymous23
  • 1,088
  • 2
  • 10
  • 24

6 Answers6

18

You should expose an ObservableCollection<string>, which implements the INotifyCollectionChange interface to raise its own change events.

You should also remove the property setter; Collection properties should be read only.

You should not raise the PropertyChanged event when the contents of the collection change.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Be sure to look through the unanswered questions and pay it forward by sharing your expertise. This site works because people give back. – William Leader Jun 07 '10 at 22:10
4

Ok I just finally experienced this issue, and there are NO complete answers on the Internet afaikt, so here is the missing piece that no one mentions (maybe because the assume that we are not complete morons and have NOT deleted the default constructor, or have alteast extended the default constructor) anyhow:

Make certain that you DID NOT delete the InitializeComponent(); call in the constructor of your View.

Without this call BEFORE you set DataContext of the view, NotifyPropertyChanged Event will ALWAYS BE NULL. I spent about 2 hours trying to figure out what was different between two different MVVM userControls. I guess my mind is so used to seeing InitializeComponent(); that it did not register that it was missing. I added that back and viola!

Hope This Helps Other Dummies Like Me! Cheers, Code Warrior Malo

  • Thanks for this! I had the same issue. I'd made my class as a standard C# class but after switching it to a Forms XAML with code behind it started working (seems you need the code behind XAML to get the `InitializeComponent()` method to work) – CMash Dec 28 '17 at 22:41
1

It's not firing because the collection reference isn't changing, just the contents. You'd need the collection's Add() method to fire the event to be able to see it.

Josh Sterling
  • 838
  • 7
  • 12
1

have a look at System.Collections.ObjectModel.ObservableCollection. http://msdn.microsoft.com/en-us/library/ms668604.aspx

It can be used like a List but has events built in for when its contents change.

William Leader
  • 814
  • 6
  • 20
0

ObservableCollection is your answer. If you want to fire on collection property changes, you'll need to implement INotifyPropertyChanged for each of the properties you'd like to track.

Robaticus
  • 22,857
  • 5
  • 54
  • 63
0

You should add an event listener to your _answers collection. Unfortunately, List<T> doesn't provide such an event.

As a suggestion, manage _answers as an ObservableCollection<string>, and properly attach/detach an event handler for the CollectionChanged event, as follows:

public ObservableCollection<string> Answers
{
    get { return _answers;  }
    set
    {
      // Detach the event handler from current instance, if any:
      if (_answers != null)
      {
         _answers.CollectionChanged -= _answers_CollectionChanged;
      }

      _answers = value;

      // Attatach the event handler to the new instance, if any:
      if (_answers != null)
      {
         _answers.CollectionChanged += _answers_CollectionChanged;
      }

      // Notify that the 'Answers' property has changed:
      onPropertyChanged("Answers");
    }
}

private void _answers_CollectionChanged(object sender,
NotifyCollectionChangedEventArgs e)
{
   onPropertyChanged("Answers");
}
Humberto
  • 7,117
  • 4
  • 31
  • 46