Pourquoi ReadOnlyObservableCollection.CollectionChanged
est-il protégé et non public (comme le ObservableCollection.CollectionChanged
is correspondant)?
Quelle est l'utilisation d'une collection implémentant INotifyCollectionChanged
si je ne peux pas accéder à l'événement CollectionChanged
?
Voici la solution: Événements CollectionChanged sur ReadOnlyObservableCollection
Vous devez cast la collection vers INotifyCollectionChanged .
J'ai trouvé un moyen pour vous de procéder:
ObservableCollection<string> obsCollection = new ObservableCollection<string>();
INotifyCollectionChanged collection = new ReadOnlyObservableCollection<string>(obsCollection);
collection.CollectionChanged += new NotifyCollectionChangedEventHandler(collection_CollectionChanged);
Il vous suffit de faire explicitement référence à votre collection par INotifyCollectionChanged interface.
Vous pouvez voter pour l’entrée de bogue sur Microsoft Connect qui décrit ce problème: https://connect.Microsoft.com/VisualStudio/feedback/details/641395/readonlyobservablecollection-t-collectionchanged-event-should-be-public
Mise à jour:
Le portail Connect a été arrêté par Microsoft. Donc, le lien ci-dessus ne fonctionne plus.
La bibliothèque My Win Application Framework (WAF) fournit une solution: ReadOnlyObservableList class:
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; }
}
}
Je sais que cet article est vieux, cependant, les gens devraient prendre leur temps pour comprendre les modèles utilisés dans .NET avant de commenter. Une collection en lecture seule est un wrapper sur une collection existante qui empêche les utilisateurs de le modifier directement. Regardez ReadOnlyCollection
et vous verrez qu'il s'agit d'un wrapper sur un IList<T>
qui peut ou non être mutable. Les collections immuables sont une autre affaire et sont couvertes par la nouvelle bibliothèque de collections immuables
En d'autres termes, la lecture seule n'est pas la même chose que l'immuable !!!!
Ceci mis à part, ReadOnlyObservableCollection
devrait implémenter implicitement INotifyCollectionChanged
.
Il existe certainement de bonnes raisons de vouloir souscrire aux notifications de collecte modifiées sur un ReadOnlyObservableCollection . Ainsi, au lieu de simplement convertir votre collection sous la forme INotifyCollectionChanged , si vous vous trouvez en sous-classe ReadOnlyObservableCollection , la procédure suivante constitue un moyen plus pratique sur le plan de la syntaxe d'accéder à a CollectionChanged. événement:
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; }
}
}
Cela a bien fonctionné pour moi avant.
C'était un succès sur Google, alors j'ai décidé d'ajouter ma solution au cas où d'autres personnes le consulteraient.
En utilisant les informations ci-dessus (sur le besoin de transtyper vers INotifyCollectionChanged ), j'ai créé deux méthodes d'extension pour enregistrer et annuler l'enregistrement.
Ma solution - Méthodes d'extension
public static void RegisterCollectionChanged(this INotifyCollectionChanged collection, NotifyCollectionChangedEventHandler handler)
{
collection.CollectionChanged += handler;
}
public static void UnregisterCollectionChanged(this INotifyCollectionChanged collection, NotifyCollectionChangedEventHandler handler)
{
collection.CollectionChanged -= handler;
}
Exemple
IThing.cs
public interface IThing
{
string Name { get; }
ReadOnlyObservableCollection<int> Values { get; }
}
Utilisation des méthodes d'extension
public void AddThing(IThing thing)
{
//...
thing.Values.RegisterCollectionChanged(this.HandleThingCollectionChanged);
}
public void RemoveThing(IThing thing)
{
//...
thing.Values.UnregisterCollectionChanged(this.HandleThingCollectionChanged);
}
Solution OP
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;
}
Alternative 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;
}