INotifyPropertyChange ~ PropertyChanged не запускается, когда свойство является коллекцией, а в коллекцию добавляется новый элемент - PullRequest
4 голосов
/ 07 июня 2010

У меня есть класс, который реализует интерфейс INotifyPropertyChanged.Некоторые свойства класса имеют тип List.Например:

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

Если я назначу для ответа новый список , то событие PropertyChanged сработает, как и ожидалось;но если я добавлю строковую строку в список ответов, используя метод List Add, событие PropertyChanged не сработает.

Я подумывал добавить метод AddAnswer () в мой класс, который бы обрабатывал вызов списков.Добавьте метод и вызовите onPropertyChanged () оттуда, но это правильный способ сделать это?Есть ли более элегантный способ сделать это?

Cheers, KT

Ответы [ 6 ]

17 голосов
/ 07 июня 2010

Вы должны предоставить ObservableCollection<string>, который реализует интерфейс INotifyCollectionChange для вызова своих собственных событий изменения.

Вы также должны удалить установщик свойства; Свойства коллекции должны быть доступны только для чтения .

Вы не должны вызывать событие PropertyChanged при изменении содержимого коллекции.

3 голосов
/ 20 июля 2012

Хорошо. Я только что наконец-то столкнулся с этой проблемой, и в Интернете НЕТ полных ответов, так что здесь есть недостающий фрагмент, о котором никто не упоминает (возможно, потому, что предполагается, что мы не полные дебилы и НЕ удалили конструктор по умолчанию). или alteast расширил конструктор по умолчанию) так или иначе:

Убедитесь, что вы НЕ удаляли InitializeComponent (); вызовите конструктор вашего представления.

Без этого вызова ДО ТОГО, как вы установите DataContext для представления, событие NotifyPropertyChanged ВСЕГДА БУДЕТ ПУСТО. Я потратил около 2 часов, пытаясь выяснить, что отличалось между двумя различными пользовательскими элементами управления MVVM. Я думаю, что мой разум так привык видеть InitializeComponent (); что он не зарегистрировал, что пропал без вести. Я добавил это обратно и альт!

Надеюсь, это поможет другим чайникам, как я! Ура, Код Воина Мало

1 голос
/ 07 июня 2010

взгляните на System.Collections.ObjectModel.ObservableCollection. http://msdn.microsoft.com/en-us/library/ms668604.aspx

Он может использоваться как список, но имеет встроенные события для изменения его содержимого.

1 голос
/ 07 июня 2010

Это не стрельба, потому что ссылка на коллекцию не меняется, только содержимое. Вам понадобится метод Add () коллекции, чтобы запустить событие, чтобы увидеть его.

0 голосов
/ 07 июня 2010

Вы должны добавить прослушиватель событий в вашу коллекцию _answers. К сожалению, List<T> не предоставляет такого события.

В качестве рекомендации управляйте _answers как ObservableCollection<string> и правильно подключайте / отключайте обработчик события для CollectionChanged, как показано ниже:

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");
}
0 голосов
/ 07 июня 2010

ObservableCollection - ваш ответ. Если вы хотите инициировать изменения свойств коллекции, вам нужно реализовать INotifyPropertyChanged для каждого из свойств, которые вы хотите отслеживать.

...