11
votes

I have a class:

public class A : INotifyPropertyChanged
{
    public List<B> bList { get; set; } 

    public void AddB(B b)
    {
        bList.Add(b);
        NotifyPropertyChanged("bList");
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
}

And a binding (DataContext of UserControl is an instance of A):

<ListBox ItemsSource="{Binding Path=bList}" />

Elements are shown, the ListBox is not updated after new object is added to List

After changing list to ObservableCollection and removing the NotifyPropertyChanged handler everything works.

Why the list is not working?

5
Please post your real code... The code you posted can't work, even with an ObservableCollection. And the NotifyPropertyChanged changes nothing, since you're not using itThomas Levesque

5 Answers

16
votes

Your property has to be public, or the binding engine won't be able to access it.


EDIT:

After changing list to ObservableCollection and removing the NotifyPropertyChanged handler everything works.

That's precisely why the ObservableCollection<T> class was introduced... ObservableCollection<T> implements INotifyCollectionChanged, which allows it to notify the UI when an item is added/removed/replaced. List<T> doesn't trigger any notification, so the UI can't detect when the content of the list has changed.

The fact that you raise the PropertyChanged event does refresh the binding, but then it realizes that it's the same instance of List<T> as before, so it reuses the same ICollectionView as the ItemsSource, and the content of the ListBox isn't refreshed.

0
votes

First thought is that you're trying to bind to a private member. That certainly doesn't seem right.

0
votes

I think that the problem is that, although you are notifying the binding framework that the property has changed, the actual value of the property remains the same. That is to say that although the listbox may reevaluate the value of its ItemsSource binding, it will find that it is still the same object instance as previously. For example, imagine that the listbox reacts by to the property changed event somehow similar to the below.

private void OnItemsSourceBindingChanged()
{
    var newValue = this.EvaluateItemsSourceBinding();
    if (newValue != this.ItemsSource) //it will be equal, as its still the same list
    {
        this.AddNewItems();
    }
}

In your example, this would mean that it would not reevaluate the items.

Note: I do not know how the listbox works with the ItemsSource property - I'm just speculating!

0
votes

ObservableCollections send CollectionChanged events not PropertyChanged events

0
votes

By signaling

NotifyPropertyChanged("bList");

you are basically saying you have a new list object, not that the content of the List has changed.

If you Change the type to ObservableCollection, the collections automatically sends

CollectionChanged

notifications that the collection items have changed, which is what you want.