WPF: Список привязок к ListBox

У меня есть класс:

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));
        }
    }
}

И привязка (DataContext UserControl - это экземпляр A):

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

Элементы показаны, ListBox не обновляется после добавления нового объекта в список

После изменения списка на ObservableCollection и удаления обработчика NotifyPropertyChanged все работает.

Почему список не работает?

Ответ 1

Ваше свойство должно быть public, или механизм привязки не сможет получить к нему доступ.


EDIT:

После изменения списка на ObservableCollection и удаления обработчика NotifyPropertyChanged все работает.

Именно поэтому был введен класс ObservableCollection<T>... ObservableCollection<T> реализует INotifyCollectionChanged, что позволяет ему уведомлять пользовательский интерфейс, когда элемент добавляется/удаляется/заменяется. List<T> не вызывает никаких уведомлений, поэтому пользовательский интерфейс не может обнаружить, когда содержимое списка изменилось.

Тот факт, что вы поднимаете событие PropertyChanged, обновляет привязку, но затем он понимает, что он тот же самый экземпляр List<T>, как и раньше, поэтому он повторно использует те же ICollectionView, что и ItemsSource, и содержимое ListBox не обновляется.

Ответ 2

Первой мыслью является то, что вы пытаетесь привязать к частному участнику. Это, конечно, не кажется правильным.

Ответ 3

Я думаю, что проблема в том, что, хотя вы уведомляете структуру привязки, что свойство изменилось, фактическое значение свойства остается неизменным. То есть, хотя listbox может переоценить значение привязки ItemsSource, он обнаружит, что он по-прежнему является тем же экземпляром объекта, что и ранее. Например, представьте, что listbox реагирует на событие с измененным свойством, каким-то образом похожим на ниже.

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

В вашем примере это означает, что он не будет переоценивать элементы.

Примечание. Я не знаю, как работает listbox с свойством ItemsSource - я просто размышляю!

Ответ 5

По сигналу

NotifyPropertyChanged("bList");

вы в основном говорите, что у вас есть новый список, а не то, что содержимое списка изменилось.

Если вы измените тип на ObservableCollection, коллекции автоматически отправят

CollectionChanged

уведомления о том, что коллекция элементов изменилась, что вам нужно.