Почему ReadOnlyObservableCollection.CollectionChanged не является общедоступным? - PullRequest
79 голосов
/ 13 января 2010

Почему ReadOnlyObservableCollection.CollectionChanged защищено и не является общедоступным (как соответствующий ObservableCollection.CollectionChanged)?

Какая польза от коллекции, реализующей INotifyCollectionChanged, если я не могу получить доступ к событию CollectionChanged?

Ответы [ 6 ]

53 голосов
/ 15 января 2010

Вот решение: События CollectionChanged для ReadOnlyObservableCollection

Вы должны привести коллекцию к INotifyCollectionChanged .

14 голосов
/ 13 января 2010

Я нашел для вас способ, как это сделать:

ObservableCollection<string> obsCollection = new ObservableCollection<string>();
INotifyCollectionChanged collection = new ReadOnlyObservableCollection<string>(obsCollection);
collection.CollectionChanged += new NotifyCollectionChangedEventHandler(collection_CollectionChanged);

Вам просто нужно явно обратиться к своей коллекции с помощью интерфейса INotifyCollectionChanged .

5 голосов
/ 30 января 2014

Я знаю, что этот пост старый, но люди должны не торопиться, чтобы понять шаблоны, используемые в .NET, прежде чем комментировать. Коллекция только для чтения - это оболочка существующей коллекции, которая не позволяет потребителям изменять ее напрямую, посмотрите на ReadOnlyCollection, и вы увидите, что это оболочка на IList<T>, которая может изменяться или не изменяться. Неизменяемые коллекции - это другое дело, и они охватываются новой библиотекой неизменных коллекций

Другими словами, чтение только не является неизменным !!!!

Кроме этого, ReadOnlyObservableCollection должен неявно реализовывать INotifyCollectionChanged.

5 голосов
/ 05 октября 2011

Существуют веские причины для подписки на уведомления об изменениях в коллекции ReadOnlyObservableCollection . Таким образом, в качестве альтернативы простому приведению вашей коллекции как INotifyCollectionChanged , если вы оказались подклассом ReadOnlyObservableCollection , то следующее обеспечивает более синтаксически удобный доступ к CollectionChanged событие:

    public class ReadOnlyObservableCollectionWithCollectionChangeNotifications<T> : ReadOnlyObservableCollection<T>
{
    public ReadOnlyObservableCollectionWithCollectionChangeNotifications(ObservableCollection<T> list)
        : base(list)
    {
    }

    event System.Collections.Specialized.NotifyCollectionChangedEventHandler CollectionChanged2
    {
        add { CollectionChanged += value; }
        remove { CollectionChanged -= value; }
    }
}

Раньше мне это удавалось.

5 голосов
/ 04 февраля 2011

Вы можете проголосовать за сообщение об ошибке в Microsoft Connect, описывающее эту проблему: https://connect.microsoft.com/VisualStudio/feedback/details/641395/readonlyobservablecollection-t-collectionchanged-event-should-be-public

Обновление:

Портал Connect был закрыт Microsoft. Так что ссылка выше не работает больше.

Библиотека My Win Application Framework (WAF) предоставляет решение: ReadOnlyObservableList класс:

public class ReadOnlyObservableList<T> 
        : ReadOnlyObservableCollection<T>, IReadOnlyObservableList<T>
{
    public ReadOnlyObservableList(ObservableCollection<T> list)
        : base(list)
    {
    }

    public new event NotifyCollectionChangedEventHandler CollectionChanged
    {
        add { base.CollectionChanged += value; }
        remove { base.CollectionChanged -= value; }
    }

    public new event PropertyChangedEventHandler PropertyChanged
    {
        add { base.PropertyChanged += value; }
        remove { base.PropertyChanged -= value; }
    }
}
0 голосов
/ 08 ноября 2017

Это был самый популярный сайт в Google, поэтому я решил добавить свое решение на случай, если другие люди посмотрят это.

Используя информацию выше (о необходимости приведения к INotifyCollectionChanged ), я сделал два метода расширения для регистрации и отмены регистрации.

Мое решение - Методы расширения

public static void RegisterCollectionChanged(this INotifyCollectionChanged collection, NotifyCollectionChangedEventHandler handler)
{
    collection.CollectionChanged += handler;
}

public static void UnregisterCollectionChanged(this INotifyCollectionChanged collection, NotifyCollectionChangedEventHandler handler)
{
    collection.CollectionChanged -= handler;
}

Пример

IThing.cs

public interface IThing
{
    string Name { get; }
    ReadOnlyObservableCollection<int> Values { get; }
}

Использование методов расширения

public void AddThing(IThing thing)
{
    //...
    thing.Values.RegisterCollectionChanged(this.HandleThingCollectionChanged);
}

public void RemoveThing(IThing thing)
{
    //...
    thing.Values.UnregisterCollectionChanged(this.HandleThingCollectionChanged);
}

Решение ОП

public void AddThing(IThing thing)
{
    //...
    INotifyCollectionChanged thingCollection = thing.Values;
    thingCollection.CollectionChanged += this.HandleThingCollectionChanged;
}

public void RemoveThing(IThing thing)
{
    //...
    INotifyCollectionChanged thingCollection = thing.Values;
    thingCollection.CollectionChanged -= this.HandleThingCollectionChanged;
}

Альтернатива 2

public void AddThing(IThing thing)
{
    //...
    (thing.Values as INotifyCollectionChanged).CollectionChanged += this.HandleThingCollectionChanged;
}

public void RemoveThing(IThing thing)
{
    //...
    (thing.Values as INotifyCollectionChanged).CollectionChanged -= this.HandleThingCollectionChanged;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...