diff Source/EditableObjects/EditableArrayList.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Source/EditableObjects/EditableArrayList.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,1100 @@
+using System;
+using System.Collections;
+using System.Collections.Specialized;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Reflection;
+
+namespace BLToolkit.EditableObjects
+{
+	using Reflection;
+	using Mapping;
+	using ComponentModel;
+
+	[DebuggerDisplay("Count = {Count}, ItemType = {ItemType}")]
+	[Serializable]
+	public class EditableArrayList : ArrayList, IEditable, ISortable, ISupportMapping,
+		IDisposable, IPrintDebugState, ITypedList, IBindingListView, ICancelAddNew, INotifyCollectionChanged
+	{
+		#region Constructors
+
+		public EditableArrayList() : this(typeof(object), new ArrayList(), true)
+		{
+		}
+
+		public EditableArrayList([JetBrains.Annotations.NotNull] Type itemType, [JetBrains.Annotations.NotNull] ArrayList list, bool trackChanges)
+		{
+			if (itemType == null) throw new ArgumentNullException("itemType");
+			if (list     == null) throw new ArgumentNullException("list");
+
+			ItemType = itemType;
+			List     = list;
+
+			_noTrackingChangesCount++;
+			AddInternal(List);
+			_noTrackingChangesCount--;
+
+			if (!trackChanges)
+			{
+				SetTrackingChanges(false);
+				_minTrackingChangesCount = 1;
+			}
+		}
+
+		public EditableArrayList(Type itemType)
+			: this(itemType, new ArrayList(), true)
+		{
+		}
+
+		public EditableArrayList(Type itemType, bool trackChanges)
+			: this(itemType, new ArrayList(), trackChanges)
+		{
+		}
+
+		public EditableArrayList(Type itemType, int capacity)
+			: this(itemType, new ArrayList(capacity), true)
+		{
+		}
+
+		public EditableArrayList(Type itemType, int capacity, bool trackChanges)
+			: this(itemType, new ArrayList(capacity), trackChanges)
+		{
+		}
+
+		public EditableArrayList(Type itemType, ICollection c)
+			: this(itemType, new ArrayList(c), true)
+		{
+		}
+
+		public EditableArrayList(Type itemType, ICollection c, bool trackChanges)
+			: this(itemType, new ArrayList(c), trackChanges)
+		{
+		}
+
+		public EditableArrayList(Type itemType, ArrayList list)
+			: this(itemType, list, true)
+		{
+		}
+
+		public EditableArrayList(EditableArrayList list)
+			: this(list.ItemType, new ArrayList(list), true)
+		{
+		}
+
+		public EditableArrayList(EditableArrayList list, bool trackChanges)
+			: this(list.ItemType, new ArrayList(list), trackChanges)
+		{
+		}
+
+		public EditableArrayList(Type itemType, EditableArrayList list)
+			: this(itemType, new ArrayList(list), true)
+		{
+		}
+
+		public EditableArrayList(Type itemType, EditableArrayList list, bool trackChanges)
+			: this(itemType, new ArrayList(list), trackChanges)
+		{
+		}
+
+		#endregion
+
+		#region Public Members
+
+		internal ArrayList List     { get; private set; }
+		public   Type      ItemType { get; private set; }
+
+		private ArrayList _newItems;
+		public  ArrayList  NewItems
+		{
+			get { return _newItems ?? (_newItems = new ArrayList()); }
+		}
+
+		private ArrayList _delItems;
+		public  ArrayList  DelItems
+		{
+			get { return _delItems ?? (_delItems = new ArrayList()); }
+		}
+
+		public void Sort(params string[] memberNames)
+		{
+			Sort(ListSortDirection.Ascending, memberNames);
+		}
+
+		public void Sort(ListSortDirection direction, params string[] memberNames)
+		{
+			if (memberNames        == null) throw new ArgumentNullException      ("memberNames");
+			if (memberNames.Length == 0)    throw new ArgumentOutOfRangeException("memberNames");
+
+			Sort(new SortMemberComparer(TypeAccessor.GetAccessor(ItemType), direction, memberNames));
+		}
+
+		public void SortEx(string sortExpression)
+		{
+			var sorts = sortExpression.Split(',');
+
+			for (var i = 0; i < sorts.Length; i++)
+				sorts[i] = sorts[i].Trim();
+
+			var last = sorts[sorts.Length - 1];
+			var desc = last.ToLower().EndsWith(" desc");
+
+			if (desc)
+				sorts[sorts.Length - 1] = last.Substring(0, last.Length - " desc".Length);
+
+			Sort(desc? ListSortDirection.Descending: ListSortDirection.Ascending, sorts);
+		}
+
+		public void Move(int newIndex, int oldIndex)
+		{
+			BindingListImpl.Move(newIndex, oldIndex);
+		}
+
+		public void Move(int newIndex, object item)
+		{
+			lock (SyncRoot)
+			{
+				var index = IndexOf(item);
+
+				if (index >= 0)
+					Move(newIndex, index);
+			}
+		}
+
+		#endregion
+
+		#region Change Notification
+
+		public bool NotifyChanges
+		{
+			get { return BindingListImpl.NotifyChanges;  }
+			set { BindingListImpl.NotifyChanges = value; }
+		}
+
+		protected virtual void OnListChanged(ListChangedEventArgs e)
+		{
+			if (!_supressEvent && NotifyChanges && ListChanged != null)
+				ListChanged(this, e);
+		}
+
+		protected void OnListChanged(ListChangedType listChangedType, int index)
+		{
+			OnListChanged(new EditableListChangedEventArgs(listChangedType, index));
+		}
+
+		private void OnResetList()
+		{
+			OnListChanged(ListChangedType.Reset, -1);
+			OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+		}
+
+		private void OnAddItem(object newObject, int index)
+		{
+			OnListChanged(ListChangedType.ItemAdded, index);
+			OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, newObject, index));
+		}
+
+		#endregion
+
+		#region Add/Remove Internal
+
+		void AddInternal(object value)
+		{
+			if (IsTrackingChanges)
+			{
+				if (DelItems.Contains(value))
+					DelItems.Remove(value);
+				else
+					NewItems.Add(value);
+			}
+
+			OnAdd(value);
+		}
+
+		private void RemoveInternal(object value)
+		{
+			if (IsTrackingChanges)
+			{
+				if (NewItems.Contains(value))
+					NewItems.Remove(value);
+				else
+					DelItems.Add(value);
+			}
+
+			OnRemove(value);
+		}
+
+		private void AddInternal(IEnumerable e)
+		{
+			foreach (var o in e)
+				AddInternal(o);
+		}
+
+		private void RemoveInternal(IEnumerable e)
+		{
+			foreach (var o in e)
+				RemoveInternal(o);
+		}
+
+		protected virtual void OnAdd(object value)
+		{
+		}
+
+		protected virtual void OnRemove(object value)
+		{
+		}
+
+		#endregion
+
+		#region Track Changes
+
+		private          int _noTrackingChangesCount;
+		private readonly int _minTrackingChangesCount;
+
+		public  bool IsTrackingChanges
+		{
+			get { return _noTrackingChangesCount == 0; }
+		}
+
+		protected void SetTrackingChanges(bool trackChanges)
+		{
+			if (trackChanges)
+			{
+				_noTrackingChangesCount--;
+
+				if (_noTrackingChangesCount < _minTrackingChangesCount)
+				{
+					_noTrackingChangesCount = _minTrackingChangesCount;
+					throw new InvalidOperationException("Tracking Changes Counter can not be negative.");
+				}
+			}
+			else
+			{
+				_noTrackingChangesCount++;
+			}
+		}
+
+		#endregion
+
+		#region ISupportMapping Members
+
+		public virtual void BeginMapping(InitContext initContext)
+		{
+			if (initContext.IsDestination)
+				_noTrackingChangesCount++;
+		}
+
+		public virtual void EndMapping(InitContext initContext)
+		{
+			if (initContext.IsDestination)
+			{
+				AcceptChanges();
+				_noTrackingChangesCount--;
+			}
+		}
+
+		#endregion
+
+		#region IEditable Members
+
+		public virtual void AcceptChanges()
+		{
+			foreach (var o in List)
+			{
+				if (o is EditableObject)
+					((EditableObject)o).AcceptChanges();
+				else if (o is IEditable)
+					((IEditable)o).AcceptChanges();
+			}
+
+			_newItems = null;
+			_delItems = null;
+		}
+
+		public virtual void RejectChanges()
+		{
+			_noTrackingChangesCount++;
+
+			if (_delItems != null)
+				foreach (var o in _delItems)
+					Add(o);
+
+			if (_newItems != null)
+				foreach (var o in _newItems)
+					Remove(o);
+
+			foreach (var o in List)
+			{
+				if (o is EditableObject)
+					((EditableObject)o).RejectChanges();
+				else if (o is IEditable)
+					((IEditable)o).RejectChanges();
+			}
+
+			_noTrackingChangesCount--;
+
+			_newItems  = null;
+			_delItems  = null;
+		}
+
+		public virtual bool IsDirty
+		{
+			get
+			{
+				if (_newItems != null && _newItems.Count > 0 ||
+					_delItems != null && _delItems.Count > 0)
+					return true;
+
+				foreach (var o in List)
+				{
+					if (o is EditableObject)
+						if (((EditableObject)o).IsDirty)
+							return true;
+					else if (o is IEditable)
+						if (((IEditable)o).IsDirty)
+							return true;
+				}
+
+				return false;
+			}
+		}
+
+		void IPrintDebugState.PrintDebugState(PropertyInfo propertyInfo, ref string str)
+		{
+			var original = List.Count
+				- (_newItems == null? 0: _newItems.Count)
+				+ (_delItems == null? 0: _delItems.Count);
+
+			str += string.Format("{0,-20} {1} {2,-40} {3,-40} \r\n",
+				propertyInfo.Name, IsDirty? "*": " ", original, List.Count);
+		}
+
+		#endregion
+
+		#region IList Members
+
+		public override bool IsFixedSize
+		{
+			get { return BindingListImpl.IsFixedSize; }
+		}
+
+		public override bool IsReadOnly
+		{
+			get { return BindingListImpl.IsReadOnly; }
+		}
+
+		public override object this[int index]
+		{
+			get { return BindingListImpl[index];  }
+			set
+			{
+				var o = BindingListImpl[index];
+
+				if (o != value)
+				{
+					RemoveInternal(o);
+					AddInternal(value);
+				}
+				
+				BindingListImpl[index] = value;
+			}
+		} 
+
+		public override int Add(object value)
+		{
+			AddInternal(value);
+
+			return BindingListImpl.Add(value);
+		}
+
+		public override void Clear()
+		{
+			if (List.Count > 0)
+				RemoveInternal(List);
+			
+			BindingListImpl.Clear();
+		}
+
+		public override bool Contains(object item)
+		{
+			return BindingListImpl.Contains(item);
+		}
+
+		public override int IndexOf(object value)
+		{
+			return BindingListImpl.IndexOf(value);
+		}
+
+		public override void Insert(int index, object value)
+		{
+			AddInternal(value);
+
+			BindingListImpl.Insert(index, value);
+		}
+
+		public override void Remove(object value)
+		{
+			RemoveInternal(value);
+
+			BindingListImpl.Remove(value);
+		}
+
+		public override void RemoveAt(int index)
+		{
+			RemoveInternal(BindingListImpl[index]);
+			
+			BindingListImpl.RemoveAt(index);
+		}
+		
+		#endregion
+
+		#region ICollection Members
+
+		public override int Count
+		{
+			get { return BindingListImpl.Count; }
+		}
+
+		public override bool IsSynchronized
+		{
+			get { return BindingListImpl.IsSynchronized; }
+		}
+
+		public override object SyncRoot
+		{
+			get { return BindingListImpl.SyncRoot; }
+		}
+
+		public override void CopyTo(Array array, int arrayIndex)
+		{
+			BindingListImpl.CopyTo(array, arrayIndex);
+		}
+		
+		#endregion
+
+		#region IEnumerable Members
+
+		public override IEnumerator GetEnumerator()
+		{
+			return BindingListImpl.GetEnumerator();
+		}
+		
+		#endregion
+
+		#region Overridden Methods
+
+		public int Add(object value, bool trackChanges)
+		{
+			if (!trackChanges) _noTrackingChangesCount++;
+			var idx = Add(value);
+			if (!trackChanges) _noTrackingChangesCount--;
+
+			return idx;
+		}
+
+		public override void AddRange(ICollection c)
+		{
+			if (c.Count == 0)
+				return;
+			
+			AddInternal(c);
+
+			BindingListImpl.AddRange(c);
+		}
+
+		public void AddRange(ICollection c, bool trackChanges)
+		{
+			if (c.Count == 0)
+				return;
+
+			if (!trackChanges) _noTrackingChangesCount++;
+			AddRange(c);
+			if (!trackChanges) _noTrackingChangesCount--;
+		}
+
+		public override int BinarySearch(int index, int count, object value, IComparer comparer)
+		{
+			return List.BinarySearch(index, count, value, comparer);
+		}
+
+		public override int BinarySearch(object value)
+		{
+			return List.BinarySearch(value);
+		}
+
+		public override int BinarySearch(object value, IComparer comparer)
+		{
+			return List.BinarySearch(value, comparer);
+		}
+
+		public override int Capacity
+		{
+			get { return List.Capacity;  }
+			set { List.Capacity = value; }
+		}
+
+		public void Clear(bool trackChanges)
+		{
+			if (!trackChanges) _noTrackingChangesCount++;
+			Clear();
+			if (!trackChanges) _noTrackingChangesCount--;
+		}
+
+		protected EditableArrayList Clone(EditableArrayList el)
+		{
+			if (_newItems != null) el._newItems = (ArrayList)_newItems.Clone();
+			if (_delItems != null) el._delItems = (ArrayList)_delItems.Clone();
+
+			el.NotifyChanges           = NotifyChanges;
+			el._noTrackingChangesCount = _noTrackingChangesCount;
+
+			return el;
+		}
+
+		public override object Clone()
+		{
+			return Clone(new EditableArrayList(ItemType, (ArrayList)List.Clone()));
+		}
+
+		public override void CopyTo(int index, Array array, int arrayIndex, int count)
+		{
+			List.CopyTo(index, array, arrayIndex, count);
+		}
+
+		public override void CopyTo(Array array)
+		{
+			List.CopyTo(array);
+		}
+
+		public override bool Equals(object obj)
+		{
+			return List.Equals(obj);
+		}
+
+		public override IEnumerator GetEnumerator(int index, int count)
+		{
+			return List.GetEnumerator(index, count);
+		}
+
+		public override int GetHashCode()
+		{
+			return List.GetHashCode();
+		}
+
+		public override ArrayList GetRange(int index, int count)
+		{
+			return List.GetRange(index, count);
+		}
+
+		public override int IndexOf(object value, int startIndex)
+		{
+			return List.IndexOf(value, startIndex);
+		}
+
+		public override int IndexOf(object value, int startIndex, int count)
+		{
+			return List.IndexOf(value, startIndex, count);
+		}
+
+		public void Insert(int index, object value, bool trackChanges)
+		{
+			if (!trackChanges) _noTrackingChangesCount++;
+			Insert(index, value);
+			if (!trackChanges) _noTrackingChangesCount--;
+		}
+
+		public override void InsertRange(int index, ICollection c)
+		{
+			BindingListImpl.InsertRange(index, c);
+		}
+
+		public void InsertRange(int index, ICollection c, bool trackChanges)
+		{
+			if (!trackChanges) _noTrackingChangesCount++;
+			InsertRange(index, c);
+			if (!trackChanges) _noTrackingChangesCount--;
+		}
+
+		public override int LastIndexOf(object value)
+		{
+			return List.LastIndexOf(value);
+		}
+
+		public override int LastIndexOf(object value, int startIndex)
+		{
+			return List.LastIndexOf(value, startIndex);
+		}
+
+		public override int LastIndexOf(object value, int startIndex, int count)
+		{
+			return List.LastIndexOf(value, startIndex, count);
+		}
+
+		public void Remove(object obj, bool trackChanges)
+		{
+			if (!trackChanges) _noTrackingChangesCount++;
+			Remove(obj);
+			if (!trackChanges) _noTrackingChangesCount--;
+		}
+
+		public void RemoveAt(int index, bool trackChanges)
+		{
+			if (!trackChanges) _noTrackingChangesCount++;
+			RemoveAt(index);
+			if (!trackChanges) _noTrackingChangesCount--;
+		}
+
+		public override void RemoveRange(int index, int count)
+		{
+			RemoveInternal(GetRange(index, count));
+
+			BindingListImpl.RemoveRange(index, count);
+		}
+
+		public void RemoveRange(int index, int count, bool trackChanges)
+		{
+			if (!trackChanges) _noTrackingChangesCount++;
+			RemoveRange(index, count);
+			if (!trackChanges) _noTrackingChangesCount--;
+		}
+
+		public override void Reverse()
+		{
+			BindingListImpl.EndNew();
+
+			if (!BindingListImpl.IsSorted)
+				List.Reverse();
+			else
+				throw new InvalidOperationException("Reverse is not supported for already sorted arrays. Invoke IBindingList.RemoveSort() first or provide reverse sort direction.");
+
+			if (List.Count > 1)
+				OnResetList();
+		}
+
+		public override void Reverse(int index, int count)
+		{
+			BindingListImpl.EndNew();
+
+			if (!BindingListImpl.IsSorted)
+				List.Reverse(index, count);
+			else
+				throw new InvalidOperationException("Range Reverse is not supported for already sorted arrays. Invoke IBindingList.RemoveSort() first.");
+
+			if (count > 1)
+				OnResetList();
+		}
+
+		public override void SetRange(int index, ICollection c)
+		{
+			if (c.Count == 0)
+				return;
+
+			AddInternal(c);
+
+			BindingListImpl.SetRange(index, c);
+		}
+
+		public override void Sort()
+		{
+			BindingListImpl.EndNew();
+
+			if (!BindingListImpl.IsSorted)
+			{
+				List.Sort();
+
+				if (List.Count > 1)
+					OnResetList();
+			}
+			else
+			{
+				if (BindingListImpl.SortProperty != null)
+					BindingListImpl.ApplySort(BindingListImpl.SortProperty, BindingListImpl.SortDirection);
+				else if (BindingListImpl.SortDescriptions != null)
+					BindingListImpl.ApplySort(BindingListImpl.SortDescriptions);
+				else
+					throw new InvalidOperationException("Currently applied sort method is not recognized/supported by EditableArrayList.");
+			}
+		}
+
+		public override void Sort(int index, int count, IComparer comparer)
+		{
+			BindingListImpl.EndNew();
+
+			if (!BindingListImpl.IsSorted)
+				List.Sort(index, count, comparer);
+			else
+				throw new InvalidOperationException("Custom sorting is not supported on already sorted arrays. Invoke IBindingList.RemoveSort first.");
+
+			if (count > 1)
+				OnResetList();
+		}
+
+		public override void Sort(IComparer comparer)
+		{
+			BindingListImpl.EndNew();
+
+			if (!BindingListImpl.IsSorted)
+				List.Sort(comparer);
+			else
+				throw new InvalidOperationException("Custom sorting is not supported on already sorted arrays. Invoke IBindingList.RemoveSort first.");
+
+			if (List.Count > 1)
+				OnResetList();
+		}
+
+		public override object[] ToArray()
+		{
+			return List.ToArray();
+		}
+
+		public override Array ToArray(Type type)
+		{
+			return List.ToArray(type);
+		}
+
+		public override string ToString()
+		{
+			return List.ToString();
+		}
+
+		public override void TrimToSize()
+		{
+			List.TrimToSize();
+		}
+
+		#endregion
+
+		#region Static Methods
+
+		public static EditableArrayList Adapter(Type itemType, IList list)
+		{
+			if (list == null) throw new ArgumentNullException("list");
+
+			if (list.IsFixedSize)
+				return new EditableArrayList(itemType, new ArrayList(list));
+
+			return list is ArrayList?
+				new EditableArrayList(itemType, (ArrayList)list):
+				new EditableArrayList(itemType, ArrayList.Adapter(list));
+		}
+
+		public static new EditableArrayList Adapter(IList list)
+		{
+			return Adapter(TypeHelper.GetListItemType(list), list);
+		}
+
+		#endregion
+
+		#region IDisposable
+
+		public void Dispose()
+		{
+			Clear();
+		}
+
+		#endregion
+
+		#region SortMemberComparer
+
+		class SortMemberComparer : IComparer
+		{
+			readonly ListSortDirection  _direction;
+			readonly string[]           _memberNames;
+			readonly TypeAccessor       _typeAccessor;
+			readonly MemberAccessor[]   _members;
+			readonly MemberAccessor     _member;
+
+			public SortMemberComparer(TypeAccessor typeAccessor, ListSortDirection direction, string[] memberNames)
+			{
+				_typeAccessor = typeAccessor;
+				_direction    = direction;
+				_memberNames  = memberNames;
+				_members      = new MemberAccessor[memberNames.Length];
+
+				_member = _members[0] = _typeAccessor[memberNames[0]];
+
+				if (_member == null)
+					throw new InvalidOperationException(
+						string.Format("Field '{0}.{1}' not found.",
+							_typeAccessor.OriginalType.Name, _memberNames[0]));
+			}
+
+			public int Compare(object x, object y)
+			{
+				var a = _member.GetValue(x);
+				var b = _member.GetValue(y);
+				var n = Comparer.Default.Compare(a, b);
+
+				if (n == 0) for (var i = 1; n == 0 && i < _members.Length; i++)
+				{
+					var member = _members[i];
+
+					if (member == null)
+					{
+						member = _members[i] = _typeAccessor[_memberNames[i]];
+
+						if (member == null)
+							throw new InvalidOperationException(
+								string.Format("Field '{0}.{1}' not found.",
+									_typeAccessor.OriginalType.Name, _memberNames[i]));
+					}
+
+					a = member.GetValue(x);
+					b = member.GetValue(y);
+					n = Comparer.Default.Compare(a, b);
+				}
+
+				return _direction == ListSortDirection.Ascending? n: -n;
+			}
+		}
+
+		#endregion
+
+		#region ITypedList Members
+
+		[NonSerialized]
+		private TypedListImpl _typedListImpl;
+		private TypedListImpl  TypedListImpl
+		{
+			get { return _typedListImpl ?? (_typedListImpl = new TypedListImpl(ItemType)); }
+		}
+
+		public PropertyDescriptorCollection GetItemProperties(PropertyDescriptor[] listAccessors)
+		{
+			return GetItemProperties(listAccessors, null, null, true);
+		}
+
+		public PropertyDescriptorCollection GetItemProperties(
+			PropertyDescriptor[] listAccessors,
+			Type                 objectViewType,
+			IsNullHandler        isNull,
+			bool                 cache)
+		{
+			return TypedListImpl.GetItemProperties(listAccessors, objectViewType, isNull, cache);
+		}
+
+		public string GetListName(PropertyDescriptor[] listAccessors)
+		{
+			return TypedListImpl.GetListName(listAccessors);
+		}
+
+		#endregion
+
+		#region IBindingList Members
+
+		sealed class BindingListImplInternal : BindingListImpl
+		{
+			readonly EditableArrayList _owner;
+
+			public BindingListImplInternal(IList list, Type itemType, EditableArrayList owner)
+				: base(list, itemType)
+			{
+				_owner = owner;
+			}
+
+			protected override void OnListChanged(EditableListChangedEventArgs e)
+			{
+				_owner.OnListChanged(e);
+			}
+
+			protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs ea)
+			{
+				_owner.OnCollectionChanged(ea);
+			}
+		}
+
+		[NonSerialized]
+		private BindingListImpl _bindingListImpl;
+		private BindingListImpl  BindingListImpl
+		{
+			get { return _bindingListImpl ?? (_bindingListImpl = new BindingListImplInternal(List, ItemType, this)); }
+		}
+
+		public void AddIndex(PropertyDescriptor property)
+		{
+			BindingListImpl.AddIndex(property);
+		}
+
+		public object AddNew()
+		{
+			object newObject;
+
+			try
+			{
+				BeginSuppressEvent();
+				newObject = BindingListImpl.AddNew();
+			}
+			finally
+			{
+				EndSuppressEvent();
+			}
+
+			AddInternal(newObject);
+
+			var index = IndexOf(newObject);
+
+			EndSuppressEvent();
+			OnAddItem(newObject, index);
+
+			return newObject;
+		}
+
+		public bool AllowEdit
+		{
+			get { return BindingListImpl.AllowEdit; }
+		}
+
+		public bool AllowNew
+		{
+			get { return BindingListImpl.AllowNew; }
+		}
+
+		public bool AllowRemove
+		{
+			get { return BindingListImpl.AllowRemove; }
+		}
+
+		public void ApplySort(PropertyDescriptor property, ListSortDirection direction)
+		{
+			BindingListImpl.ApplySort(property, direction);
+		}
+
+		public int Find(PropertyDescriptor property, object key)
+		{
+			return BindingListImpl.Find(property, key);
+		}
+
+		public bool IsSorted
+		{
+			get { return BindingListImpl.IsSorted; }
+		}
+
+		public void RemoveIndex(PropertyDescriptor property)
+		{
+			BindingListImpl.RemoveIndex(property);
+		}
+
+		public void RemoveSort()
+		{
+			BindingListImpl.RemoveSort();
+		}
+
+		public ListSortDirection SortDirection
+		{
+			get { return BindingListImpl.SortDirection; }
+		}
+
+		public PropertyDescriptor SortProperty
+		{
+			get { return BindingListImpl.SortProperty; }
+		}
+
+		public bool SupportsChangeNotification
+		{
+			get { return BindingListImpl.SupportsChangeNotification; }
+		}
+
+		public event ListChangedEventHandler ListChanged;
+
+		private bool _supressEvent;
+
+		private void BeginSuppressEvent()
+		{
+			_supressEvent = true;
+		}
+
+		private void EndSuppressEvent()
+		{
+			_supressEvent = false;
+		}
+
+		public bool SupportsSearching
+		{
+			get { return BindingListImpl.SupportsSearching; }
+		}
+
+		public bool SupportsSorting
+		{
+			get { return BindingListImpl.SupportsSorting; }
+		}
+
+		#endregion
+
+		#region Sorting Enhancement
+
+		public void CreateSortSubstitution(string originalProperty, string substituteProperty)
+		{
+			BindingListImpl.CreateSortSubstitution(originalProperty, substituteProperty);
+		}
+
+		public void RemoveSortSubstitution(string originalProperty)
+		{
+			BindingListImpl.RemoveSortSubstitution(originalProperty);
+		}
+
+		#endregion
+
+		#region IBindingListView Members
+
+		public void ApplySort(ListSortDescriptionCollection sorts)
+		{
+			BindingListImpl.ApplySort(sorts);
+		}
+
+		public string Filter
+		{
+			get { return BindingListImpl.Filter;  }
+			set { BindingListImpl.Filter = value; }
+		}
+
+		public void RemoveFilter()
+		{
+			BindingListImpl.RemoveFilter();
+		}
+
+		public ListSortDescriptionCollection SortDescriptions
+		{
+			get { return BindingListImpl.SortDescriptions; }
+		}
+
+		public bool SupportsAdvancedSorting
+		{
+			get { return BindingListImpl.SupportsAdvancedSorting; }
+		}
+
+		public bool SupportsFiltering
+		{
+			get { return BindingListImpl.SupportsFiltering; }
+		}
+
+		#endregion
+
+		#region ICancelAddNew Members
+
+		public void CancelNew(int itemIndex)
+		{
+			if (itemIndex >= 0 && itemIndex < List.Count)
+				NewItems.Remove(List[itemIndex]);
+
+			BindingListImpl.CancelNew(itemIndex);
+		}
+
+		public void EndNew(int itemIndex)
+		{
+			BindingListImpl.EndNew(itemIndex);
+		}
+
+		#endregion
+
+		#region INotifyCollectionChanged Members
+
+		public event NotifyCollectionChangedEventHandler CollectionChanged;
+
+		protected virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
+		{
+			if (!_supressEvent && NotifyChanges && CollectionChanged != null)
+				CollectionChanged(this, e);
+		}
+
+		#endregion
+	}
+}