Рішення
ReadOnlyObservableCollection.CollectionChanged не виставляється (з поважних причин, викладених в інших відповідях), тому давайте створимо власний клас обгортки, який його викриває:
public class ObservableReadOnlyCollection<T> : ReadOnlyObservableCollection<T>
{
public new NotifyCollectionChangedEventHandler CollectionChanged;
public ObservableReadOnlyCollection(ObservableCollection<T> list) : base(list) { }
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs args) =>
CollectionChanged?.Invoke(this, args);
}
Пояснення
Люди запитували, чому ви хочете спостерігати за змінами до колекції лише для читання, тож я поясню одну з багатьох дійсних ситуацій; коли колекція лише для читання обгортає приватну внутрішню колекцію, яка може змінюватися.
Ось один із таких сценаріїв:
Припустимо, у вас є послуга, яка дозволяє додавати та видаляти елементи до внутрішньої колекції поза межами служби. Тепер припустимо, ви хочете виставити значення колекції, але не хочете, щоб споживачі безпосередньо маніпулювали колекцією; так ви обертаєте внутрішню колекцію в ReadOnlyObservableCollection.
Зауважимо, що для того, щоб обернути внутрішню колекцію ReadOnlyObservableCollectionвнутрішньою колекцією, ObservableCollectionконструктор змушує її виводити ReadOnlyObservableCollection.
Тепер припустимо, ви хочете повідомити споживачів про послугу, коли змінюється внутрішня колекція (а отже, і коли відкриті ReadOnlyObservableCollectionзміни). Замість того , щоб коченню своєї власної реалізації , ви просто хочете , щоб викрити CollectionChangedз ReadOnlyObservableCollection. Замість того, щоб змусити споживача зробити припущення про реалізацію ReadOnlyObservableCollection, ви просто поміняєте ReadOnlyObservableCollectionцей користувальницький вміст ObservableReadOnlyCollectionі все готово.
У ObservableReadOnlyCollectionшкура ReadOnlyObservableCollection.CollectionChangedз його власним, і просто проходить по всім масиву змінених подій в будь-якому прикріпленого обробник подій.