//-------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: ObservableConcurrentCollection.cs // //-------------------------------------------------------------------------- using System.Collections.Specialized; using System.ComponentModel; using System.Threading; using System.Diagnostics; namespace System.Collections.Concurrent { /// /// Provides a thread-safe, concurrent collection for use with data binding. /// /// Specifies the type of the elements in this collection. [DebuggerDisplay("Count={Count}")] [DebuggerTypeProxy(typeof(IProducerConsumerCollection_DebugView<>))] public class ObservableConcurrentCollection : ProducerConsumerCollectionBase, INotifyCollectionChanged, INotifyPropertyChanged { private readonly SynchronizationContext _context; /// /// Initializes an instance of the ObservableConcurrentCollection class with an underlying /// queue data structure. /// public ObservableConcurrentCollection() : this(new ConcurrentQueue()) { } /// /// Initializes an instance of the ObservableConcurrentCollection class with the specified /// collection as the underlying data structure. /// public ObservableConcurrentCollection(IProducerConsumerCollection collection) : base(collection) { _context = AsyncOperationManager.SynchronizationContext; } /// Event raised when the collection changes. public event NotifyCollectionChangedEventHandler CollectionChanged; /// Event raised when a property on the collection changes. public event PropertyChangedEventHandler PropertyChanged; /// /// Notifies observers of CollectionChanged or PropertyChanged of an update to the dictionary. /// private void NotifyObserversOfChange() { var collectionHandler = CollectionChanged; var propertyHandler = PropertyChanged; if (collectionHandler != null || propertyHandler != null) { _context.Post(s => { if (collectionHandler != null) { collectionHandler(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } if (propertyHandler != null) { propertyHandler(this, new PropertyChangedEventArgs("Count")); } }, null); } } protected override bool TryAdd(T item) { // Try to add the item to the underlying collection. If we were able to, // notify any listeners. bool result = base.TryAdd(item); if (result) NotifyObserversOfChange(); return result; } protected override bool TryTake(out T item) { // Try to remove an item from the underlying collection. If we were able to, // notify any listeners. bool result = base.TryTake(out item); if (result) NotifyObserversOfChange(); return result; } } }