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 - я просто размышляю!
Ответ 4
ObservableCollections отправляет События CollectionChanged не события PropertyChanged
Ответ 5
По сигналу
NotifyPropertyChanged("bList");
вы в основном говорите, что у вас есть новый список, а не то, что содержимое списка изменилось.
Если вы измените тип на ObservableCollection, коллекции автоматически отправят
CollectionChanged
уведомления о том, что коллекция элементов изменилась, что вам нужно.