using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Threading;
namespace System.Collections.ObjectModel
{
/// <summary>Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.</summary>
/// <typeparam name="T">The type of elements in the collection.</typeparam>
[Serializable,__DynamicallyInvokable]
public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged
{
// Fields
private SimpleMonitor _monitor;
[NonSerialized]
private NotifyCollectionChangedEventHandler m_collectionChanged;
private const string CountString = "Count";
private const string IndexerName = "Item[]";
[NonSerialized]
private PropertyChangedEventHandler m_propertyChanged;
// Events
[__DynamicallyInvokable]
public event NotifyCollectionChangedEventHandler CollectionChanged
{
[__DynamicallyInvokable]
add
{
NotifyCollectionChangedEventHandler handler2;
NotifyCollectionChangedEventHandler collectionChanged = m_collectionChanged;
do
{
handler2 = collectionChanged;
NotifyCollectionChangedEventHandler handler3 = (NotifyCollectionChangedEventHandler)Delegate.Combine(handler2, value);
collectionChanged = Interlocked.CompareExchange<NotifyCollectionChangedEventHandler>(ref m_collectionChanged, handler3, handler2);
}
while (collectionChanged != handler2);
}
[__DynamicallyInvokable]
remove
{
NotifyCollectionChangedEventHandler handler2;
NotifyCollectionChangedEventHandler collectionChanged = m_collectionChanged;
do
{
handler2 = collectionChanged;
NotifyCollectionChangedEventHandler handler3 = (NotifyCollectionChangedEventHandler)Delegate.Remove(handler2, value);
collectionChanged = Interlocked.CompareExchange<NotifyCollectionChangedEventHandler>(ref m_collectionChanged, handler3, handler2);
}
while (collectionChanged != handler2);
}
}
[__DynamicallyInvokable]
protected event PropertyChangedEventHandler PropertyChanged
{
[__DynamicallyInvokable]
add
{
PropertyChangedEventHandler handler2;
PropertyChangedEventHandler propertyChanged = m_propertyChanged;
do
{
handler2 = propertyChanged;
PropertyChangedEventHandler handler3 = (PropertyChangedEventHandler)Delegate.Combine(handler2, value);
propertyChanged = Interlocked.CompareExchange<PropertyChangedEventHandler>(ref m_propertyChanged, handler3, handler2);
}
while (propertyChanged != handler2);
}
[__DynamicallyInvokable]
remove
{
PropertyChangedEventHandler handler2;
PropertyChangedEventHandler propertyChanged = m_propertyChanged;
do
{
handler2 = propertyChanged;
PropertyChangedEventHandler handler3 = (PropertyChangedEventHandler)Delegate.Remove(handler2, value);
propertyChanged = Interlocked.CompareExchange<PropertyChangedEventHandler>(ref m_propertyChanged, handler3, handler2);
}
while (propertyChanged != handler2);
}
}
[__DynamicallyInvokable]
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
{
[__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
add
{
m_propertyChanged += value;
}
[__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
remove
{
m_propertyChanged -= value;
}
}
// Methods
[__DynamicallyInvokable]
public ObservableCollection()
{
this._monitor = new SimpleMonitor();
}
[__DynamicallyInvokable]
public ObservableCollection(IEnumerable<T> collection)
{
this._monitor = new SimpleMonitor();
if (collection == null)
{
throw new ArgumentNullException("collection");
}
this.CopyFrom(collection);
}
public ObservableCollection(List<T> list)
: base((list != null) ? new List<T>(list.Count) : list)
{
this._monitor = new SimpleMonitor();
this.CopyFrom(list);
}
[__DynamicallyInvokable]
protected IDisposable BlockReentrancy()
{
this._monitor.Enter();
return this._monitor;
}
[__DynamicallyInvokable]
protected void CheckReentrancy()
{
if ((this._monitor.Busy && (m_collectionChanged != null)) && (m_collectionChanged.GetInvocationList().Length > 1))
{
throw new InvalidOperationException("ObservableCollectionReentrancyNotAllowed");
}
}
[__DynamicallyInvokable]
protected override void ClearItems()
{
this.CheckReentrancy();
base.ClearItems();
this.OnPropertyChanged("Count");
this.OnPropertyChanged("Item[]");
this.OnCollectionReset();
}
private void CopyFrom(IEnumerable<T> collection)
{
IList<T> items = base.Items;
if ((collection != null) && (items != null))
{
using (IEnumerator<T> enumerator = collection.GetEnumerator())
{
while (enumerator.MoveNext())
{
items.Add(enumerator.Current);
}
}
}
}
[__DynamicallyInvokable]
protected override void InsertItem(int index, T item)
{
this.CheckReentrancy();
base.InsertItem(index, item);
this.OnPropertyChanged("Count");
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
}
[__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public void Move(int oldIndex, int newIndex)
{
this.MoveItem(oldIndex, newIndex);
}
[__DynamicallyInvokable]
protected virtual void MoveItem(int oldIndex, int newIndex)
{
this.CheckReentrancy();
T item = base[oldIndex];
base.RemoveItem(oldIndex);
base.InsertItem(newIndex, item);
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(NotifyCollectionChangedAction.Move, item, newIndex, oldIndex);
}
[__DynamicallyInvokable]
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (m_collectionChanged != null)
{
using (this.BlockReentrancy())
{
m_collectionChanged(this, e);
}
}
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index)
{
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index));
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index, int oldIndex)
{
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index, oldIndex));
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, object oldItem, object newItem, int index)
{
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItem, oldItem, index));
}
private void OnCollectionReset()
{
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
[__DynamicallyInvokable]
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (m_propertyChanged != null)
{
m_propertyChanged(this, e);
}
}
private void OnPropertyChanged(string propertyName)
{
this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
[__DynamicallyInvokable]
protected override void RemoveItem(int index)
{
this.CheckReentrancy();
T item = base[index];
base.RemoveItem(index);
this.OnPropertyChanged("Count");
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(NotifyCollectionChangedAction.Remove, item, index);
}
[__DynamicallyInvokable]
protected override void SetItem(int index, T item)
{
this.CheckReentrancy();
T oldItem = base[index];
base.SetItem(index, item);
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(NotifyCollectionChangedAction.Replace, oldItem, item, index);
}
// Nested Types
[Serializable]
private class SimpleMonitor : IDisposable
{
// Fields
private int _busyCount;
// Methods
public void Dispose()
{
this._busyCount--;
}
public void Enter()
{
this._busyCount++;
}
// Properties
public bool Busy
{
get
{
return (this._busyCount > 0);
}
}
}
}
}
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Runtime;
using System.Runtime.CompilerServices;
using System.Threading;
namespace System.Collections.ObjectModel
{
/// <summary>Represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed.</summary>
/// <typeparam name="T">The type of elements in the collection.</typeparam>
[Serializable,__DynamicallyInvokable]
public class ObservableCollection<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged
{
// Fields
private SimpleMonitor _monitor;
[NonSerialized]
private NotifyCollectionChangedEventHandler m_collectionChanged;
private const string CountString = "Count";
private const string IndexerName = "Item[]";
[NonSerialized]
private PropertyChangedEventHandler m_propertyChanged;
// Events
[__DynamicallyInvokable]
public event NotifyCollectionChangedEventHandler CollectionChanged
{
[__DynamicallyInvokable]
add
{
NotifyCollectionChangedEventHandler handler2;
NotifyCollectionChangedEventHandler collectionChanged = m_collectionChanged;
do
{
handler2 = collectionChanged;
NotifyCollectionChangedEventHandler handler3 = (NotifyCollectionChangedEventHandler)Delegate.Combine(handler2, value);
collectionChanged = Interlocked.CompareExchange<NotifyCollectionChangedEventHandler>(ref m_collectionChanged, handler3, handler2);
}
while (collectionChanged != handler2);
}
[__DynamicallyInvokable]
remove
{
NotifyCollectionChangedEventHandler handler2;
NotifyCollectionChangedEventHandler collectionChanged = m_collectionChanged;
do
{
handler2 = collectionChanged;
NotifyCollectionChangedEventHandler handler3 = (NotifyCollectionChangedEventHandler)Delegate.Remove(handler2, value);
collectionChanged = Interlocked.CompareExchange<NotifyCollectionChangedEventHandler>(ref m_collectionChanged, handler3, handler2);
}
while (collectionChanged != handler2);
}
}
[__DynamicallyInvokable]
protected event PropertyChangedEventHandler PropertyChanged
{
[__DynamicallyInvokable]
add
{
PropertyChangedEventHandler handler2;
PropertyChangedEventHandler propertyChanged = m_propertyChanged;
do
{
handler2 = propertyChanged;
PropertyChangedEventHandler handler3 = (PropertyChangedEventHandler)Delegate.Combine(handler2, value);
propertyChanged = Interlocked.CompareExchange<PropertyChangedEventHandler>(ref m_propertyChanged, handler3, handler2);
}
while (propertyChanged != handler2);
}
[__DynamicallyInvokable]
remove
{
PropertyChangedEventHandler handler2;
PropertyChangedEventHandler propertyChanged = m_propertyChanged;
do
{
handler2 = propertyChanged;
PropertyChangedEventHandler handler3 = (PropertyChangedEventHandler)Delegate.Remove(handler2, value);
propertyChanged = Interlocked.CompareExchange<PropertyChangedEventHandler>(ref m_propertyChanged, handler3, handler2);
}
while (propertyChanged != handler2);
}
}
[__DynamicallyInvokable]
event PropertyChangedEventHandler INotifyPropertyChanged.PropertyChanged
{
[__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
add
{
m_propertyChanged += value;
}
[__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
remove
{
m_propertyChanged -= value;
}
}
// Methods
[__DynamicallyInvokable]
public ObservableCollection()
{
this._monitor = new SimpleMonitor();
}
[__DynamicallyInvokable]
public ObservableCollection(IEnumerable<T> collection)
{
this._monitor = new SimpleMonitor();
if (collection == null)
{
throw new ArgumentNullException("collection");
}
this.CopyFrom(collection);
}
public ObservableCollection(List<T> list)
: base((list != null) ? new List<T>(list.Count) : list)
{
this._monitor = new SimpleMonitor();
this.CopyFrom(list);
}
[__DynamicallyInvokable]
protected IDisposable BlockReentrancy()
{
this._monitor.Enter();
return this._monitor;
}
[__DynamicallyInvokable]
protected void CheckReentrancy()
{
if ((this._monitor.Busy && (m_collectionChanged != null)) && (m_collectionChanged.GetInvocationList().Length > 1))
{
throw new InvalidOperationException("ObservableCollectionReentrancyNotAllowed");
}
}
[__DynamicallyInvokable]
protected override void ClearItems()
{
this.CheckReentrancy();
base.ClearItems();
this.OnPropertyChanged("Count");
this.OnPropertyChanged("Item[]");
this.OnCollectionReset();
}
private void CopyFrom(IEnumerable<T> collection)
{
IList<T> items = base.Items;
if ((collection != null) && (items != null))
{
using (IEnumerator<T> enumerator = collection.GetEnumerator())
{
while (enumerator.MoveNext())
{
items.Add(enumerator.Current);
}
}
}
}
[__DynamicallyInvokable]
protected override void InsertItem(int index, T item)
{
this.CheckReentrancy();
base.InsertItem(index, item);
this.OnPropertyChanged("Count");
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
}
[__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
public void Move(int oldIndex, int newIndex)
{
this.MoveItem(oldIndex, newIndex);
}
[__DynamicallyInvokable]
protected virtual void MoveItem(int oldIndex, int newIndex)
{
this.CheckReentrancy();
T item = base[oldIndex];
base.RemoveItem(oldIndex);
base.InsertItem(newIndex, item);
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(NotifyCollectionChangedAction.Move, item, newIndex, oldIndex);
}
[__DynamicallyInvokable]
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (m_collectionChanged != null)
{
using (this.BlockReentrancy())
{
m_collectionChanged(this, e);
}
}
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index)
{
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index));
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, object item, int index, int oldIndex)
{
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, item, index, oldIndex));
}
private void OnCollectionChanged(NotifyCollectionChangedAction action, object oldItem, object newItem, int index)
{
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(action, newItem, oldItem, index));
}
private void OnCollectionReset()
{
this.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
[__DynamicallyInvokable]
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (m_propertyChanged != null)
{
m_propertyChanged(this, e);
}
}
private void OnPropertyChanged(string propertyName)
{
this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
[__DynamicallyInvokable]
protected override void RemoveItem(int index)
{
this.CheckReentrancy();
T item = base[index];
base.RemoveItem(index);
this.OnPropertyChanged("Count");
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(NotifyCollectionChangedAction.Remove, item, index);
}
[__DynamicallyInvokable]
protected override void SetItem(int index, T item)
{
this.CheckReentrancy();
T oldItem = base[index];
base.SetItem(index, item);
this.OnPropertyChanged("Item[]");
this.OnCollectionChanged(NotifyCollectionChangedAction.Replace, oldItem, item, index);
}
// Nested Types
[Serializable]
private class SimpleMonitor : IDisposable
{
// Fields
private int _busyCount;
// Methods
public void Dispose()
{
this._busyCount--;
}
public void Enter()
{
this._busyCount++;
}
// Properties
public bool Busy
{
get
{
return (this._busyCount > 0);
}
}
}
}
}