1007 lines
33 KiB
C#
1007 lines
33 KiB
C#
#if FRAMEWORK20
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using System.Collections;
|
|
using System.Diagnostics;
|
|
using System.Runtime.InteropServices;
|
|
using System.Collections.ObjectModel;
|
|
using System.ComponentModel;
|
|
using System.Collections.Specialized;
|
|
|
|
namespace DevComponents.Schedule.Model.Primitives
|
|
{
|
|
/// <summary>
|
|
/// Represents custom collection with INotifyPropertyChanged and INotifyCollectionChanged interface support.
|
|
/// </summary>
|
|
/// <typeparam name="T"></typeparam>
|
|
[Serializable, DebuggerDisplay("Count = {Count}"), ComVisible(false)]
|
|
public class CustomCollection<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable, INotifyPropertyChanged, INotifyCollectionChanged
|
|
{
|
|
#region Events
|
|
/// <summary>
|
|
/// Occurs when property value has changed.
|
|
/// </summary>
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
#endregion
|
|
|
|
#region Internal Implementation
|
|
private SimpleMonitor<T> _monitor;
|
|
|
|
[NonSerialized]
|
|
private object _syncRoot;
|
|
private IList<T> items;
|
|
|
|
/// <summary>
|
|
/// Creates new instance of object.
|
|
/// </summary>
|
|
public CustomCollection()
|
|
{
|
|
this._monitor = new SimpleMonitor<T>();
|
|
this.items = new List<T>();
|
|
}
|
|
/// <summary>
|
|
/// Creates new instance of object.
|
|
/// </summary>
|
|
/// <param name="list">List to initialize collection with.</param>
|
|
public CustomCollection(IList<T> list)
|
|
{
|
|
if (list == null)
|
|
{
|
|
throw new ArgumentNullException("list");
|
|
}
|
|
this._monitor = new SimpleMonitor<T>();
|
|
this.items = list;
|
|
}
|
|
/// <summary>
|
|
/// Add item to collection.
|
|
/// </summary>
|
|
/// <param name="item">Item to add.</param>
|
|
public void Add(T item)
|
|
{
|
|
if (this.items.IsReadOnly)
|
|
{
|
|
throw new NotSupportedException("collection is read-only");
|
|
}
|
|
int count = this.items.Count;
|
|
this.InsertItem(count, item);
|
|
}
|
|
/// <summary>
|
|
/// Remove all items from collection.
|
|
/// </summary>
|
|
public void Clear()
|
|
{
|
|
if (this.items.IsReadOnly)
|
|
{
|
|
throw new NotSupportedException("collection is read-only");
|
|
}
|
|
this.ClearItems();
|
|
}
|
|
/// <summary>
|
|
/// Remove all items from collection.
|
|
/// </summary>
|
|
protected virtual void ClearItems()
|
|
{
|
|
this.CheckReentrancy();
|
|
this.items.Clear();
|
|
OnPropertyChanged(new PropertyChangedEventArgs(this.CountString));
|
|
OnPropertyChanged(new PropertyChangedEventArgs(this.ItemString));
|
|
this.OnCollectionReset();
|
|
}
|
|
/// <summary>
|
|
/// Checks whether collection contains item.
|
|
/// </summary>
|
|
/// <param name="item">Item to look for.</param>
|
|
/// <returns>true if item is in collection.</returns>
|
|
public bool Contains(T item)
|
|
{
|
|
OnCollectionReadAccess();
|
|
return this.items.Contains(item);
|
|
}
|
|
/// <summary>
|
|
/// Copy collection to array.
|
|
/// </summary>
|
|
/// <param name="array">Array to copy to.</param>
|
|
/// <param name="index">Index to copy from.</param>
|
|
public void CopyTo(T[] array, int index)
|
|
{
|
|
OnCollectionReadAccess();
|
|
this.items.CopyTo(array, index);
|
|
}
|
|
/// <summary>
|
|
/// Gets enumerator for collection.
|
|
/// </summary>
|
|
/// <returns>Enumerator.</returns>
|
|
public IEnumerator<T> GetEnumerator()
|
|
{
|
|
OnCollectionReadAccess();
|
|
return this.items.GetEnumerator();
|
|
}
|
|
/// <summary>
|
|
/// Returns index of an item.
|
|
/// </summary>
|
|
/// <param name="item">Reference to item.</param>
|
|
/// <returns>Index of item.</returns>
|
|
public int IndexOf(T item)
|
|
{
|
|
OnCollectionReadAccess();
|
|
return this.items.IndexOf(item);
|
|
}
|
|
/// <summary>
|
|
/// Insert item at specified location.
|
|
/// </summary>
|
|
/// <param name="index">Index to insert item in.</param>
|
|
/// <param name="item">Item to insert.</param>
|
|
public void Insert(int index, T item)
|
|
{
|
|
if ((index < 0) || (index > this.items.Count))
|
|
{
|
|
throw new ArgumentOutOfRangeException("index");
|
|
}
|
|
this.InsertItem(index, item);
|
|
}
|
|
/// <summary>
|
|
/// Inserts item.
|
|
/// </summary>
|
|
/// <param name="index">Index to insert item at.</param>
|
|
/// <param name="item">Reference to item.</param>
|
|
protected virtual void InsertItem(int index, T item)
|
|
{
|
|
this.CheckReentrancy();
|
|
this.items.Insert(index, item);
|
|
OnPropertyChanged(new PropertyChangedEventArgs(this.CountString));
|
|
this.OnCollectionChanged(NotifyCollectionChangedAction.Add, item, index);
|
|
}
|
|
|
|
private static bool IsCompatibleObject(object value)
|
|
{
|
|
if (!(value is T) && ((value != null) || typeof(T).IsValueType))
|
|
{
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
/// <summary>
|
|
/// Removes item from collection.
|
|
/// </summary>
|
|
/// <param name="item">Item to remove.</param>
|
|
/// <returns>true if item was removed.</returns>
|
|
public bool Remove(T item)
|
|
{
|
|
if (this.items.IsReadOnly)
|
|
{
|
|
throw new NotSupportedException("collection is read-only");
|
|
}
|
|
int index = this.items.IndexOf(item);
|
|
if (index < 0)
|
|
{
|
|
return false;
|
|
}
|
|
this.RemoveItem(index);
|
|
return true;
|
|
}
|
|
/// <summary>
|
|
/// Remove item at specified location.
|
|
/// </summary>
|
|
/// <param name="index">Index of item to remove.</param>
|
|
public void RemoveAt(int index)
|
|
{
|
|
if (this.items.IsReadOnly)
|
|
{
|
|
throw new NotSupportedException("collection is read-only");
|
|
}
|
|
if ((index < 0) || (index >= this.items.Count))
|
|
{
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
this.RemoveItem(index);
|
|
}
|
|
/// <summary>
|
|
/// Remove item at specified location.
|
|
/// </summary>
|
|
/// <param name="index">Index of item to remove.</param>
|
|
protected virtual void RemoveItem(int index)
|
|
{
|
|
this.CheckReentrancy();
|
|
|
|
object item = items[index];
|
|
this.items.RemoveAt(index);
|
|
OnPropertyChanged(new PropertyChangedEventArgs(this.CountString));
|
|
this.OnCollectionChanged(NotifyCollectionChangedAction.Remove, item, index);
|
|
}
|
|
/// <summary>
|
|
/// Set item on location.
|
|
/// </summary>
|
|
/// <param name="index">Index</param>
|
|
/// <param name="item">Item to assign.</param>
|
|
protected virtual void SetItem(int index, T item)
|
|
{
|
|
this.CheckReentrancy();
|
|
T oldItem = items[index];
|
|
this.items[index] = item;
|
|
OnPropertyChanged(new PropertyChangedEventArgs(this.CountString));
|
|
OnPropertyChanged(new PropertyChangedEventArgs(this.ItemString));
|
|
this.OnCollectionChanged(NotifyCollectionChangedAction.Replace, oldItem, item, index);
|
|
}
|
|
|
|
void ICollection.CopyTo(Array array, int index)
|
|
{
|
|
this.CheckReentrancy();
|
|
OnCollectionReadAccess();
|
|
if (array == null)
|
|
{
|
|
throw new ArgumentNullException("array");
|
|
}
|
|
if (array.Rank != 1)
|
|
{
|
|
throw new ArgumentException("Argument array.Rank multi-dimensional not supported");
|
|
}
|
|
if (array.GetLowerBound(0) != 0)
|
|
{
|
|
throw new ArgumentException("Argument array non zero lower bound not supported");
|
|
}
|
|
if (index < 0)
|
|
{
|
|
throw new ArgumentOutOfRangeException("index must be non-negative number");
|
|
}
|
|
if ((array.Length - index) < this.Count)
|
|
{
|
|
throw new ArgumentException("array too small");
|
|
}
|
|
T[] localArray = array as T[];
|
|
if (localArray != null)
|
|
{
|
|
this.items.CopyTo(localArray, index);
|
|
}
|
|
else
|
|
{
|
|
Type elementType = array.GetType().GetElementType();
|
|
Type c = typeof(T);
|
|
if (!elementType.IsAssignableFrom(c) && !c.IsAssignableFrom(elementType))
|
|
{
|
|
throw new ArgumentException("Argument array of invalid type");
|
|
}
|
|
object[] objArray = array as object[];
|
|
if (objArray == null)
|
|
{
|
|
throw new ArgumentException("Argument array invalid type");
|
|
}
|
|
int count = this.items.Count;
|
|
try
|
|
{
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
objArray[index++] = this.items[i];
|
|
}
|
|
}
|
|
catch (ArrayTypeMismatchException)
|
|
{
|
|
throw new ArgumentException("Argument array invalid type");
|
|
}
|
|
}
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
{
|
|
OnCollectionReadAccess();
|
|
return this.items.GetEnumerator();
|
|
}
|
|
|
|
int IList.Add(object value)
|
|
{
|
|
if (this.items.IsReadOnly)
|
|
{
|
|
throw new NotSupportedException("collection is read-only");
|
|
}
|
|
VerifyValueType(value);
|
|
this.Add((T)value);
|
|
return (this.Count - 1);
|
|
}
|
|
|
|
private static void VerifyValueType(object value)
|
|
{
|
|
if (!IsCompatibleObject(value))
|
|
{
|
|
throw new ArgumentException("value is of wrong type");
|
|
}
|
|
}
|
|
|
|
|
|
bool IList.Contains(object value)
|
|
{
|
|
return (CustomCollection<T>.IsCompatibleObject(value) && this.Contains((T)value));
|
|
}
|
|
|
|
int IList.IndexOf(object value)
|
|
{
|
|
OnCollectionReadAccess();
|
|
if (CustomCollection<T>.IsCompatibleObject(value))
|
|
{
|
|
return this.IndexOf((T)value);
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void IList.Insert(int index, object value)
|
|
{
|
|
if (this.items.IsReadOnly)
|
|
{
|
|
throw new NotSupportedException("collection is read-only");
|
|
}
|
|
VerifyValueType(value);
|
|
this.Insert(index, (T)value);
|
|
}
|
|
|
|
void IList.Remove(object value)
|
|
{
|
|
if (this.items.IsReadOnly)
|
|
{
|
|
throw new NotSupportedException("collection is read-only");
|
|
}
|
|
if (CustomCollection<T>.IsCompatibleObject(value))
|
|
{
|
|
this.Remove((T)value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns number of items in collection.
|
|
/// </summary>
|
|
public int Count
|
|
{
|
|
get
|
|
{
|
|
OnCollectionReadAccess();
|
|
return this.items.Count;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns item at index.
|
|
/// </summary>
|
|
/// <param name="index">Index of item.</param>
|
|
/// <returns>Item at index.</returns>
|
|
public T this[int index]
|
|
{
|
|
get
|
|
{
|
|
OnCollectionReadAccess();
|
|
return this.items[index];
|
|
}
|
|
set
|
|
{
|
|
if (this.items.IsReadOnly)
|
|
{
|
|
throw new NotSupportedException("collection is read-only");
|
|
}
|
|
if ((index < 0) || (index >= this.items.Count))
|
|
{
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
this.SetItem(index, value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the IList interface for items in collection.
|
|
/// </summary>
|
|
protected IList<T> Items
|
|
{
|
|
get
|
|
{
|
|
OnCollectionReadAccess();
|
|
return this.items;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Returns items directly without checks.
|
|
/// </summary>
|
|
/// <returns>List of items.</returns>
|
|
protected IList<T> GetItemsDirect()
|
|
{
|
|
return this.items;
|
|
}
|
|
|
|
bool ICollection<T>.IsReadOnly
|
|
{
|
|
get
|
|
{
|
|
return this.items.IsReadOnly;
|
|
}
|
|
}
|
|
|
|
bool ICollection.IsSynchronized
|
|
{
|
|
get
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
object ICollection.SyncRoot
|
|
{
|
|
get
|
|
{
|
|
if (this._syncRoot == null)
|
|
{
|
|
ICollection items = this.items as ICollection;
|
|
if (items != null)
|
|
{
|
|
this._syncRoot = items.SyncRoot;
|
|
}
|
|
else
|
|
{
|
|
System.Threading.Interlocked.CompareExchange(ref this._syncRoot, new object(), null);
|
|
}
|
|
}
|
|
return this._syncRoot;
|
|
}
|
|
}
|
|
|
|
bool IList.IsFixedSize
|
|
{
|
|
get
|
|
{
|
|
IList items = this.items as IList;
|
|
return ((items != null) && items.IsFixedSize);
|
|
}
|
|
}
|
|
|
|
bool IList.IsReadOnly
|
|
{
|
|
get
|
|
{
|
|
return this.items.IsReadOnly;
|
|
}
|
|
}
|
|
|
|
object IList.this[int index]
|
|
{
|
|
get
|
|
{
|
|
OnCollectionReadAccess();
|
|
return this.items[index];
|
|
}
|
|
set
|
|
{
|
|
VerifyValueType(value);
|
|
this[index] = (T)value;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Occurs when collection is read.
|
|
/// </summary>
|
|
protected virtual void OnCollectionReadAccess()
|
|
{
|
|
}
|
|
/// <summary>
|
|
/// Occurs when collection property has changed.
|
|
/// </summary>
|
|
/// <param name="e">Event arguments.</param>
|
|
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
|
|
{
|
|
if (this.PropertyChanged != null)
|
|
{
|
|
this.PropertyChanged(this, e);
|
|
}
|
|
}
|
|
|
|
private string CountString
|
|
{
|
|
get { return "Count"; }
|
|
}
|
|
private string ItemString
|
|
{
|
|
get { return "Item[]"; }
|
|
}
|
|
/// <summary>
|
|
/// Blocks the collection re-entrancy.
|
|
/// </summary>
|
|
/// <returns>IDisposable to end re-entrancy</returns>
|
|
protected IDisposable BlockReentrancy()
|
|
{
|
|
this._monitor.Enter();
|
|
return this._monitor;
|
|
}
|
|
/// <summary>
|
|
/// Checks whether call creates re-entrancy.
|
|
/// </summary>
|
|
protected void CheckReentrancy()
|
|
{
|
|
if ((this._monitor.Busy && (this.CollectionChanged != null)) && (this.CollectionChanged.GetInvocationList().Length > 1))
|
|
{
|
|
throw new InvalidOperationException("CustomCollectionReentrancyNotAllowed");
|
|
}
|
|
}
|
|
|
|
|
|
#region SimpleMonitor
|
|
[Serializable]
|
|
private class SimpleMonitor<TY> : 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);
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#endregion
|
|
|
|
#region INotifyCollectionChanged Members
|
|
/// <summary>
|
|
/// Occurs when collection has changed.
|
|
/// </summary>
|
|
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
|
|
|
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));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Called when collection has changed.
|
|
/// </summary>
|
|
/// <param name="e">Event arguments.</param>
|
|
protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
|
{
|
|
if (this.CollectionChanged != null)
|
|
{
|
|
using (this.BlockReentrancy())
|
|
{
|
|
this.CollectionChanged(this, e);
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
#region INotifyCollectionChanged
|
|
/// <summary>
|
|
/// Represents collection changed notification interface.
|
|
/// </summary>
|
|
public interface INotifyCollectionChanged
|
|
{
|
|
/// <summary>
|
|
/// Occurs when collection changed.
|
|
/// </summary>
|
|
event NotifyCollectionChangedEventHandler CollectionChanged;
|
|
}
|
|
/// <summary>
|
|
/// Defines change actions.
|
|
/// </summary>
|
|
public enum NotifyCollectionChangedAction
|
|
{
|
|
/// <summary>
|
|
/// Items were added.
|
|
/// </summary>
|
|
Add,
|
|
/// <summary>
|
|
/// Items were removed.
|
|
/// </summary>
|
|
Remove,
|
|
/// <summary>
|
|
/// Items were replaced.
|
|
/// </summary>
|
|
Replace,
|
|
/// <summary>
|
|
/// Items were moved.
|
|
/// </summary>
|
|
Move,
|
|
/// <summary>
|
|
/// Collection was reset.
|
|
/// </summary>
|
|
Reset
|
|
}
|
|
/// <summary>
|
|
/// Defines delegate for collection notification events.
|
|
/// </summary>
|
|
/// <param name="sender">Event sender.</param>
|
|
/// <param name="e">Event arguments.</param>
|
|
public delegate void NotifyCollectionChangedEventHandler(object sender, NotifyCollectionChangedEventArgs e);
|
|
/// <summary>
|
|
/// Defines collection change notification event arguments.
|
|
/// </summary>
|
|
public class NotifyCollectionChangedEventArgs : EventArgs
|
|
{
|
|
#region Private Vars
|
|
private NotifyCollectionChangedAction _action;
|
|
private IList _newItems;
|
|
private int _newStartingIndex;
|
|
private IList _oldItems;
|
|
private int _oldStartingIndex;
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Create new instance of object.
|
|
/// </summary>
|
|
/// <param name="action">Action</param>
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if (action != NotifyCollectionChangedAction.Reset)
|
|
{
|
|
throw new ArgumentException("WrongActionForCtor");
|
|
}
|
|
this.InitializeAdd(action, null, -1);
|
|
}
|
|
/// <summary>
|
|
/// Creates new instance of object.
|
|
/// </summary>
|
|
/// <param name="action">Specifies action.</param>
|
|
/// <param name="changedItems">List of changed items.</param>
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList changedItems)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if (((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)) && (action != NotifyCollectionChangedAction.Reset))
|
|
{
|
|
throw new ArgumentException("MustBeResetAddOrRemoveActionForCtor");
|
|
}
|
|
if (action == NotifyCollectionChangedAction.Reset)
|
|
{
|
|
if (changedItems != null)
|
|
{
|
|
throw new ArgumentException("ResetActionRequiresNullItem");
|
|
}
|
|
this.InitializeAdd(action, null, -1);
|
|
}
|
|
else
|
|
{
|
|
if (changedItems == null)
|
|
{
|
|
throw new ArgumentNullException("changedItems");
|
|
}
|
|
this.InitializeAddOrRemove(action, changedItems, -1);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Creates new instance of object.
|
|
/// </summary>
|
|
/// <param name="action">Specifies action.</param>
|
|
/// <param name="changedItem">Item that was changed.</param>
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if (((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)) && (action != NotifyCollectionChangedAction.Reset))
|
|
{
|
|
throw new ArgumentException("MustBeResetAddOrRemoveActionForCtor");
|
|
}
|
|
if (action == NotifyCollectionChangedAction.Reset)
|
|
{
|
|
if (changedItem != null)
|
|
{
|
|
throw new ArgumentException("ResetActionRequiresNullItem");
|
|
}
|
|
this.InitializeAdd(action, null, -1);
|
|
}
|
|
else
|
|
{
|
|
this.InitializeAddOrRemove(action, new object[] { changedItem }, -1);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates new instance of object.
|
|
/// </summary>
|
|
/// <param name="action">Action.</param>
|
|
/// <param name="newItems">New items in collection.</param>
|
|
/// <param name="oldItems">Old items in collection.</param>
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList newItems, IList oldItems)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if (action != NotifyCollectionChangedAction.Replace)
|
|
{
|
|
throw new ArgumentException("WrongActionForCtor");
|
|
}
|
|
if (newItems == null)
|
|
{
|
|
throw new ArgumentNullException("newItems");
|
|
}
|
|
if (oldItems == null)
|
|
{
|
|
throw new ArgumentNullException("oldItems");
|
|
}
|
|
this.InitializeMoveOrReplace(action, newItems, oldItems, -1, -1);
|
|
}
|
|
/// <summary>
|
|
/// Creates new instance of object.
|
|
/// </summary>
|
|
/// <param name="action">Action.</param>
|
|
/// <param name="changedItems">List of changed items.</param>
|
|
/// <param name="startingIndex">Starting index of change.</param>
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList changedItems, int startingIndex)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if (((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)) && (action != NotifyCollectionChangedAction.Reset))
|
|
{
|
|
throw new ArgumentException("MustBeResetAddOrRemoveActionForCtor");
|
|
}
|
|
if (action == NotifyCollectionChangedAction.Reset)
|
|
{
|
|
if (changedItems != null)
|
|
{
|
|
throw new ArgumentException("ResetActionRequiresNullItem");
|
|
}
|
|
if (startingIndex != -1)
|
|
{
|
|
throw new ArgumentException("ResetActionRequiresIndexMinus1");
|
|
}
|
|
this.InitializeAdd(action, null, -1);
|
|
}
|
|
else
|
|
{
|
|
if (changedItems == null)
|
|
{
|
|
throw new ArgumentNullException("changedItems");
|
|
}
|
|
if (startingIndex < -1)
|
|
{
|
|
throw new ArgumentException("IndexCannotBeNegative");
|
|
}
|
|
this.InitializeAddOrRemove(action, changedItems, startingIndex);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Creates new instance of object.
|
|
/// </summary>
|
|
/// <param name="action">Action</param>
|
|
/// <param name="changedItem">Changed item</param>
|
|
/// <param name="index">Index of change</param>
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem, int index)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if (((action != NotifyCollectionChangedAction.Add) && (action != NotifyCollectionChangedAction.Remove)) && (action != NotifyCollectionChangedAction.Reset))
|
|
{
|
|
throw new ArgumentException("MustBeResetAddOrRemoveActionForCtor");
|
|
}
|
|
if (action == NotifyCollectionChangedAction.Reset)
|
|
{
|
|
if (changedItem != null)
|
|
{
|
|
throw new ArgumentException("ResetActionRequiresNullItem");
|
|
}
|
|
if (index != -1)
|
|
{
|
|
throw new ArgumentException("ResetActionRequiresIndexMinus1");
|
|
}
|
|
this.InitializeAdd(action, null, -1);
|
|
}
|
|
else
|
|
{
|
|
this.InitializeAddOrRemove(action, new object[] { changedItem }, index);
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Creates new instance of object.
|
|
/// </summary>
|
|
/// <param name="action">Action</param>
|
|
/// <param name="newItem">New item</param>
|
|
/// <param name="oldItem">Old item</param>
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object newItem, object oldItem)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if (action != NotifyCollectionChangedAction.Replace)
|
|
{
|
|
throw new ArgumentException("WrongActionForCtor");
|
|
}
|
|
this.InitializeMoveOrReplace(action, new object[] { newItem }, new object[] { oldItem }, -1, -1);
|
|
}
|
|
/// <summary>
|
|
/// Creates new instance of object.
|
|
/// </summary>
|
|
/// <param name="action">Action</param>
|
|
/// <param name="newItems">New items.</param>
|
|
/// <param name="oldItems">Removed items.</param>
|
|
/// <param name="startingIndex">Starting index of change.</param>
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if (action != NotifyCollectionChangedAction.Replace)
|
|
{
|
|
throw new ArgumentException("WrongActionForCtor");
|
|
}
|
|
if (newItems == null)
|
|
{
|
|
throw new ArgumentNullException("newItems");
|
|
}
|
|
if (oldItems == null)
|
|
{
|
|
throw new ArgumentNullException("oldItems");
|
|
}
|
|
this.InitializeMoveOrReplace(action, newItems, oldItems, startingIndex, startingIndex);
|
|
}
|
|
/// <summary>
|
|
/// Creates new instance of object.
|
|
/// </summary>
|
|
/// <param name="action">Action</param>
|
|
/// <param name="changedItems">Changed items</param>
|
|
/// <param name="index">New index</param>
|
|
/// <param name="oldIndex">Old index</param>
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, IList changedItems, int index, int oldIndex)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if (action != NotifyCollectionChangedAction.Move)
|
|
{
|
|
throw new ArgumentException("WrongActionForCtor");
|
|
}
|
|
if (index < 0)
|
|
{
|
|
throw new ArgumentException("IndexCannotBeNegative");
|
|
}
|
|
this.InitializeMoveOrReplace(action, changedItems, changedItems, index, oldIndex);
|
|
}
|
|
/// <summary>
|
|
/// Creates new instance of object.
|
|
/// </summary>
|
|
/// <param name="action">Action</param>
|
|
/// <param name="changedItem">Changed item</param>
|
|
/// <param name="index">New index</param>
|
|
/// <param name="oldIndex">Old index</param>
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object changedItem, int index, int oldIndex)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if (action != NotifyCollectionChangedAction.Move)
|
|
{
|
|
throw new ArgumentException("WrongActionForCtor");
|
|
}
|
|
if (index < 0)
|
|
{
|
|
throw new ArgumentException("IndexCannotBeNegative");
|
|
}
|
|
object[] newItems = new object[] { changedItem };
|
|
this.InitializeMoveOrReplace(action, newItems, newItems, index, oldIndex);
|
|
}
|
|
/// <summary>
|
|
/// Creates new instance of object.
|
|
/// </summary>
|
|
/// <param name="action">Action.</param>
|
|
/// <param name="newItem">New item</param>
|
|
/// <param name="oldItem">Old item</param>
|
|
/// <param name="index">New index</param>
|
|
public NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction action, object newItem, object oldItem, int index)
|
|
{
|
|
this._newStartingIndex = -1;
|
|
this._oldStartingIndex = -1;
|
|
if (action != NotifyCollectionChangedAction.Replace)
|
|
{
|
|
throw new ArgumentException("WrongActionForCtor");
|
|
}
|
|
this.InitializeMoveOrReplace(action, new object[] { newItem }, new object[] { oldItem }, index, index);
|
|
}
|
|
|
|
private void InitializeAdd(NotifyCollectionChangedAction action, IList newItems, int newStartingIndex)
|
|
{
|
|
this._action = action;
|
|
this._newItems = (newItems == null) ? null : ArrayList.ReadOnly(newItems);
|
|
this._newStartingIndex = newStartingIndex;
|
|
}
|
|
|
|
private void InitializeAddOrRemove(NotifyCollectionChangedAction action, IList changedItems, int startingIndex)
|
|
{
|
|
if (action == NotifyCollectionChangedAction.Add)
|
|
{
|
|
this.InitializeAdd(action, changedItems, startingIndex);
|
|
}
|
|
else if (action == NotifyCollectionChangedAction.Remove)
|
|
{
|
|
this.InitializeRemove(action, changedItems, startingIndex);
|
|
}
|
|
else
|
|
{
|
|
//Invariant.Assert(false, "Unsupported action: {0}", action.ToString());
|
|
}
|
|
}
|
|
|
|
private void InitializeMoveOrReplace(NotifyCollectionChangedAction action, IList newItems, IList oldItems, int startingIndex, int oldStartingIndex)
|
|
{
|
|
this.InitializeAdd(action, newItems, startingIndex);
|
|
this.InitializeRemove(action, oldItems, oldStartingIndex);
|
|
}
|
|
|
|
private void InitializeRemove(NotifyCollectionChangedAction action, IList oldItems, int oldStartingIndex)
|
|
{
|
|
this._action = action;
|
|
this._oldItems = (oldItems == null) ? null : ArrayList.ReadOnly(oldItems);
|
|
this._oldStartingIndex = oldStartingIndex;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the type of the collection change action.
|
|
/// </summary>
|
|
public NotifyCollectionChangedAction Action
|
|
{
|
|
get
|
|
{
|
|
return this._action;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Gets list of newly added items.
|
|
/// </summary>
|
|
public IList NewItems
|
|
{
|
|
get
|
|
{
|
|
return this._newItems;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Gets new starting index.
|
|
/// </summary>
|
|
public int NewStartingIndex
|
|
{
|
|
get
|
|
{
|
|
return this._newStartingIndex;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Gets list of removed items.
|
|
/// </summary>
|
|
public IList OldItems
|
|
{
|
|
get
|
|
{
|
|
return this._oldItems;
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Old starting index.
|
|
/// </summary>
|
|
public int OldStartingIndex
|
|
{
|
|
get
|
|
{
|
|
return this._oldStartingIndex;
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
}
|
|
#endif
|
|
|