Solução
ReadOnlyObservableCollection.CollectionChanged
não é exposto (por razões válidas descritas em outras respostas), então vamos fazer nossa própria classe de wrapper que o expõe:
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);
}
Explicação
As pessoas perguntam por que você deseja observar as alterações em uma coleção somente leitura, então explicarei uma das muitas situações válidas; quando a coleção somente leitura envolve uma coleção interna privada que pode mudar.
Aqui está um desses cenários:
Suponha que você tenha um serviço que permite adicionar e remover itens de fora do serviço para uma coleção interna. Agora suponha que você deseja expor os valores da coleção, mas não deseja que os consumidores manipulem a coleção diretamente; então você envolve a coleção interna em a ReadOnlyObservableCollection
.
Observe que para envolver a coleção interna com ReadOnlyObservableCollection
a coleção interna é forçado a derivar ObservableCollection
pelo construtor de ReadOnlyObservableCollection
.
Agora, suponha que você deseja notificar os consumidores sobre o serviço quando a coleção interna muda (e, portanto, quando a exposição ReadOnlyObservableCollection
muda). Em vez de lançar sua própria implementação, você apenas deseja expor o CollectionChanged
de ReadOnlyObservableCollection
. Em vez de forçar o consumidor a fazer uma suposição sobre a implementação do ReadOnlyObservableCollection
, você simplesmente troca o ReadOnlyObservableCollection
por este personalizado ObservableReadOnlyCollection
e pronto.
O ObservableReadOnlyCollection
oculta ReadOnlyObservableCollection.CollectionChanged
com o seu próprio e simplesmente passa todos os eventos alterados da coleção para qualquer manipulador de eventos anexado.