Fait une mise en œuvre rapide moi-même:
public class ObservableCollectionEx<T> : ObservableCollection<T> where T : INotifyPropertyChanged
{
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
Unsubscribe(e.OldItems);
Subscribe(e.NewItems);
base.OnCollectionChanged(e);
}
protected override void ClearItems()
{
foreach(T element in this)
element.PropertyChanged -= ContainedElementChanged;
base.ClearItems();
}
private void Subscribe(IList iList)
{
if (iList != null)
{
foreach (T element in iList)
element.PropertyChanged += ContainedElementChanged;
}
}
private void Unsubscribe(IList iList)
{
if (iList != null)
{
foreach (T element in iList)
element.PropertyChanged -= ContainedElementChanged;
}
}
private void ContainedElementChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged(e);
}
}
admises, il serait assez confus et trompeur d'avoir le feu PropertyChanged sur la collection lorsque la propriété qui en fait changé est un élément contenu, mais il correspond à mon objectif spécifique. Il pourrait être étendu avec un nouvel événement qui est déclenché à l'intérieur de ContainerElementChanged
Réflexions?
EDIT: Il est à noter que la BCL ObservableCollection expose que l'interface INotifyPropertyChanged par une mise en œuvre explicite de sorte que vous devrez fournir une distribution afin d'attacher à l'événement comme ceci:
ObservableCollectionEx<Element> collection = new ObservableCollectionEx<Element>();
((INotifyPropertyChanged)collection).PropertyChanged += (x,y) => ReactToChange();
EDIT2: manutention Ajouté de ClearItems, merci Josh
EDIT3: Ajout d'un désabonnement correct pour PropertyChanged, merci Mark
EDIT4: Wow, c'est apprendre-as-you-go vraiment :). KP a noté que l'événement a été déclenché avec la collection en tant qu'expéditeur et non avec l'élément lorsque l'élément a a été modifié. Il a suggéré de déclarer un événement PropertyChanged sur la classe marquée new. Cela aurait quelques questions que je vais tenter d'illustrer avec l'exemple ci-dessous:
// work on original instance
ObservableCollection<TestObject> col = new ObservableCollectionEx<TestObject>();
((INotifyPropertyChanged)col).PropertyChanged += (s, e) => { Trace.WriteLine("Changed " + e.PropertyName); };
var test = new TestObject();
col.Add(test); // no event raised
test.Info = "NewValue"; //Info property changed raised
// working on explicit instance
ObservableCollectionEx<TestObject> col = new ObservableCollectionEx<TestObject>();
col.PropertyChanged += (s, e) => { Trace.WriteLine("Changed " + e.PropertyName); };
var test = new TestObject();
col.Add(test); // Count and Item [] property changed raised
test.Info = "NewValue"; //no event raised
Vous pouvez voir de l'échantillon que « majeur » l'événement a pour effet secondaire que vous devez être extrêmement prudent dont type de variable que vous utilisez lors de l'abonnement à l'événement, car cela détermine les événements que vous recevez.
Marquer cela comme la réponse car rien de mieux (à mon avis) a fait surface –
Il y a cependant un problème avec cette classe. Si vous appelez Clear(), l'événement OnCollectionChanged recevra une notification de réinitialisation et vous n'aurez pas accès aux éléments qui ont été supprimés de la collection. Cela peut être atténué en remplaçant ClearItems et en désinscrivant les gestionnaires avant d'appeler base.ClearItems(). – Josh
Bien attrapé, Josh. J'ai mis à jour le code pour refléter cela. –