Как я могу вызвать событие CollectionChanged в ObservableCollection и передать ему измененные элементы?

У меня есть класс, который наследуется от ObservableCollection и добавляет несколько дополнительных методов, таких как AddRange и RemoveRange.

Мой базовый вызов метода таков:

public void AddRange(IEnumerable<T> collection)
{
    foreach (var i in collection) Items.Add(i);

    OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}

Моя проблема заключается в том, что я хочу получить доступ к e.NewItems или e.OldItems в событии CollectionChanged, чтобы выполнить действие над любым элементом в коллекции, а действие NotifyCollectionChangedAction.Reset не проходит в этих значениях.

void Instances_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.NewItems != null) // e.NewItems is always null
    {
        foreach (var item in e.NewItems)
        {
            if (item is EventInstanceModel)
                ((EventInstanceModel)item).ParentEvent = this;
        }
    }
}

Поэтому я подумал, что могу просто использовать NotifyCollectionChangedAction.Add вместо Reset, однако это вызывает исключение Range actions are not supported

public void AddRange(IEnumerable<T> collection)
{
    var addedItems = collection.ToList();
    foreach (var i in addedItems) Items.Add(i);

    OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, addedItems));
}

Итак, мой вопрос: как я могу вызвать событие CollectionChanged и передать ему новый или старый список элементов?


person Rachel    schedule 16.09.2011    source источник


Ответы (2)


Я изучал это, и, по-видимому, метод CollectionChanged не может быть вызван несколькими элементами.

Так что я могу позвонить

OnCollectionChanged(new NotifyCollectionChangedEventArgs(
    NotifyCollectionChangedAction.Add, singleItem));

но я не могу позвонить

OnCollectionChanged(new NotifyCollectionChangedEventArgs(
    NotifyCollectionChangedAction.Add, listOfItems));

На данный момент я просто вызываю событие Add для каждого добавленного элемента, но я все еще довольно недоволен этим, поскольку это означает, что я вызываю событие CollectionChanged для каждого элемента в методе AddRange, а не только один раз.

public void AddRange(IEnumerable<T> collection)
{
    foreach (var i in collection) 
    {
        Items.Add(i);
        OnCollectionChanged(new NotifyCollectionChangedEventArgs(
            NotifyCollectionChangedAction.Add, i));
    }
}
person Rachel    schedule 16.09.2011
comment
Вам может быть интересен этот подход: ListCollectionView/CollectionView не поддерживает NotifyCollectionChanged с несколькими элементами - person Rick Sladkey; 17.09.2011
comment
@Rick Я проверил что-то подобное, но оно не передает e.NewItems / e.OldItems в событие CollectionChanged - person Rachel; 17.09.2011
comment
Почему бы просто не поместить вызов события вне цикла foreach сразу после него, тогда он будет вызываться только один раз. - person Wobbles; 02.05.2015
comment
Этот вопрос был о том, как вызвать событие CollectionChanged с параметром каждого добавленного элемента. Ответ заключается в том, что мы должны инициировать событие отдельно для каждого элемента, поскольку оно не поддерживает инициирование с коллекцией элементов. - person Rachel; 02.05.2015

Это отлично работает для меня "автономно". Это означает, что я не использую ObservableCollection для привязки данных. Так что это не проблема ObservableCollection, а скорее ограничение ListCollectionView.

Пожалуйста, прочитайте следующую статью, это очень интересно:

Блог Натана Несбита

person SuperOli    schedule 16.09.2011
comment
Я видел эту ссылку, однако он также указывает внизу в разделе Not Quite Done, что его версия AddRange не работает, если добавляется более одного элемента из-за ограничений ListCollectionView. Вы правы, это ограничение ListCollectionView, а не ObservableCollection. - person Rachel; 16.09.2011