//--------------------------------------------------------------------------
//
// 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;
}
}
}