Рішення
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
з його власним, і просто проходить по всім масиву змінених подій в будь-якому прикріпленого обробник подій.