10using System.ComponentModel;
11using System.Collections.Generic;
12using System.Collections;
26 IList<T>, IBindingList, IEnumerable<T>, ICancelAddNew
29 #region ListItem class
31 private class ListItem : IComparable<ListItem>
35 private int _baseIndex;
44 get {
return _baseIndex; }
45 set { _baseIndex = value; }
48 public ListItem(
object key,
int baseIndex)
51 _baseIndex = baseIndex;
54 public int CompareTo(ListItem other)
56 object target = other.Key;
58 if (Key is IComparable)
59 return ((IComparable)Key).CompareTo(target);
70 else if (Key.Equals(target))
73 else if (target ==
null)
76 return Key.ToString().CompareTo(target.ToString());
80 public override string ToString()
82 return Key.ToString();
89 #region Sorted enumerator
91 private class SortedEnumerator : IEnumerator<T>
93 private IList<T> _list;
94 private List<ListItem> _sortIndex;
95 private ListSortDirection _sortOrder;
98 public SortedEnumerator(
100 List<ListItem> sortIndex,
101 ListSortDirection direction)
104 _sortIndex = sortIndex;
105 _sortOrder = direction;
111 get {
return _list[_sortIndex[_index].BaseIndex]; }
114 Object System.Collections.IEnumerator.Current
116 get {
return _list[_sortIndex[_index].BaseIndex]; }
119 public bool MoveNext()
121 if (_sortOrder == ListSortDirection.Ascending)
123 if (_index < _sortIndex.Count - 1)
145 if (_sortOrder == ListSortDirection.Ascending)
148 _index = _sortIndex.Count;
151 #region IDisposable Support
153 private bool _disposedValue =
false;
156 protected virtual void Dispose(
bool disposing)
166 _disposedValue =
true;
170 public void Dispose()
174 GC.SuppressFinalize(
this);
193 private void DoSort()
200 foreach (T obj
in _list)
202 _sortIndex.Add(
new ListItem(obj, index));
208 foreach (T obj
in _list)
210 _sortIndex.Add(
new ListItem(_sortBy.GetValue(obj), index));
218 OnListChanged(
new ListChangedEventArgs(ListChangedType.Reset, 0));
222 private void UndoSort()
226 _sortOrder = ListSortDirection.Ascending;
229 OnListChanged(
new ListChangedEventArgs(ListChangedType.Reset, 0));
235 #region IEnumerable<T>
244 return new SortedEnumerator(_list, _sortIndex, _sortOrder);
246 return _list.GetEnumerator();
251 #region IBindingList, IList<T>
260 if (_supportsBinding)
261 _bindingList.AddIndex(property);
270 if (_supportsBinding)
272 _initiatedLocally =
true;
273 result = _bindingList.AddNew();
274 _initiatedLocally =
false;
276 new ListChangedEventArgs(
277 ListChangedType.ItemAdded, _bindingList.Count - 1));
292 if (_supportsBinding)
293 return _bindingList.AllowEdit;
306 if (_supportsBinding)
307 return _bindingList.AllowNew;
320 if (_supportsBinding)
321 return _bindingList.AllowRemove;
332 public void ApplySort(
string propertyName, ListSortDirection direction)
334 _sortBy = GetPropertyDescriptor(propertyName);
345 PropertyDescriptor property, ListSortDirection direction)
348 _sortOrder = direction;
357 public int Find(
string propertyName,
object key)
359 PropertyDescriptor findProperty = GetPropertyDescriptor(propertyName);
361 return Find(findProperty, key);
365 private static PropertyDescriptor GetPropertyDescriptor(
string propertyName)
367 PropertyDescriptor
property =
null;
369 if (!String.IsNullOrEmpty(propertyName))
371 Type itemType = typeof(T);
372 foreach (PropertyDescriptor prop
in TypeDescriptor.GetProperties(itemType))
374 if (prop.Name == propertyName)
382 if (property ==
null)
395 public int Find(PropertyDescriptor property,
object key)
397 if (_supportsBinding)
399 var originalIndex = _bindingList.Find(property, key);
400 return originalIndex > -1 ? SortedIndex(originalIndex) : -1;
411 get {
return _sorted; }
443 if (_supportsBinding)
444 _bindingList.RemoveIndex(property);
460 get {
return _sortOrder; }
468 get {
return _sortBy; }
487 if (_supportsBinding)
488 return _bindingList.SupportsSearching;
507 public void CopyTo(T[] array,
int arrayIndex)
509 int pos = arrayIndex;
510 foreach (T child
in this)
517 void System.Collections.ICollection.CopyTo(System.Array array,
int index)
519 T[] tmp =
new T[array.Length];
521 Array.Copy(tmp, 0, array, index, array.Length);
529 get {
return _list.Count; }
532 bool System.Collections.ICollection.IsSynchronized
534 get {
return false; }
537 object System.Collections.ICollection.SyncRoot
539 get {
return _list; }
542 IEnumerator System.Collections.IEnumerable.GetEnumerator()
556 int System.Collections.IList.Add(
object value)
559 return SortedIndex(_list.Count - 1);
576 return _list.Contains(item);
579 bool System.Collections.IList.Contains(
object value)
590 return SortedIndex(_list.IndexOf(item));
593 int System.Collections.IList.IndexOf(
object value)
606 _list.Insert(index, item);
609 void System.Collections.IList.Insert(
int index,
object value)
614 bool System.Collections.IList.IsFixedSize
616 get {
return false; }
624 get {
return _list.IsReadOnly; }
627 object System.Collections.IList.this[
int index]
635 this[index] = (T)value;
645 return _list.Remove(item);
648 void System.Collections.IList.Remove(
object value)
666 _initiatedLocally =
true;
667 int baseIndex = OriginalIndex(index);
670 _list.RemoveAt(baseIndex);
672 _initiatedLocally =
false;
675 _list.RemoveAt(index);
683 public T
this[
int index]
688 return _list[OriginalIndex(index)];
695 _list[OriginalIndex(index)] = value;
697 _list[index] = value;
709 [EditorBrowsable(EditorBrowsableState.Advanced)]
720 private IList<T> _list;
721 private bool _supportsBinding;
722 private IBindingList _bindingList;
723 private bool _sorted;
724 private bool _initiatedLocally;
725 private PropertyDescriptor _sortBy;
726 private ListSortDirection _sortOrder =
727 ListSortDirection.Ascending;
728 private List<ListItem> _sortIndex =
729 new List<ListItem>();
740 if (_list is IBindingList)
742 _supportsBinding =
true;
743 _bindingList = (IBindingList)_list;
744 _bindingList.ListChanged +=
745 new ListChangedEventHandler(SourceChanged);
749 private void SourceChanged(
750 object sender, ListChangedEventArgs e)
754 switch (e.ListChangedType)
756 case ListChangedType.ItemAdded:
757 T newItem = _list[e.NewIndex];
758 if (e.NewIndex == _list.Count - 1)
762 newKey = _sortBy.GetValue(newItem);
766 if (_sortOrder == ListSortDirection.Ascending)
768 new ListItem(newKey, e.NewIndex));
771 new ListItem(newKey, e.NewIndex));
772 if (!_initiatedLocally)
774 new ListChangedEventArgs(
775 ListChangedType.ItemAdded,
776 SortedIndex(e.NewIndex)));
782 case ListChangedType.ItemChanged:
786 new ListChangedEventArgs(
787 ListChangedType.ItemChanged, SortedIndex(e.NewIndex), e.PropertyDescriptor));
790 case ListChangedType.ItemDeleted:
791 var internalIndex = InternalIndex(e.NewIndex);
792 var sortedIndex = internalIndex;
793 if ((_sorted) && (_sortOrder == ListSortDirection.Descending))
794 sortedIndex = _sortIndex.Count - 1 - internalIndex;
797 _sortIndex.RemoveAt(internalIndex);
800 foreach (ListItem item
in _sortIndex)
801 if (item.BaseIndex > e.NewIndex)
805 new ListChangedEventArgs(
806 ListChangedType.ItemDeleted, sortedIndex, e.PropertyDescriptor));
812 if (!_initiatedLocally)
819 if (!_initiatedLocally)
824 private int OriginalIndex(
int sortedIndex)
826 if (sortedIndex == -1)
return -1;
830 if (_sortOrder == ListSortDirection.Ascending)
831 return _sortIndex[sortedIndex].BaseIndex;
833 return _sortIndex[_sortIndex.Count - 1 - sortedIndex].BaseIndex;
839 private int SortedIndex(
int originalIndex)
841 if (originalIndex == -1)
return -1;
846 for (
int index = 0; index < _sortIndex.Count; index++)
848 if (_sortIndex[index].BaseIndex == originalIndex)
854 if (_sortOrder == ListSortDirection.Descending)
855 result = _sortIndex.Count - 1 - result;
858 result = originalIndex;
862 private int InternalIndex(
int originalIndex)
867 for (
int index = 0; index < _sortIndex.Count; index++)
869 if (_sortIndex[index].BaseIndex == originalIndex)
877 result = originalIndex;
882 #region ICancelAddNew Members
884 void ICancelAddNew.CancelNew(
int itemIndex)
886 if (itemIndex <= -1)
return;
888 ICancelAddNew can = _list as ICancelAddNew;
890 can.CancelNew(OriginalIndex(itemIndex));
892 _list.RemoveAt(OriginalIndex(itemIndex));
895 void ICancelAddNew.EndNew(
int itemIndex)
897 ICancelAddNew can = _list as ICancelAddNew;
899 can.EndNew(OriginalIndex(itemIndex));
911 List<T> result =
new List<T>();
912 foreach (T item
in this)
914 return result.ToArray();
A strongly-typed resource class, for looking up localized strings, etc.
static string SortedBindingListPropertyNameNotFound
Looks up a localized string similar to PropertyName '{0}' not found in list.
Provides a sorted view into an existing IList(Of T).
object AddNew()
Implemented by IList source object.
int Find(PropertyDescriptor property, object key)
Implemented by IList source object.
void RemoveAt(int index)
Removes the child object at the specified index in the list, resorting the display as needed.
void ApplySort(string propertyName, ListSortDirection direction)
Applies a sort to the view.
void RemoveSort()
Removes any sort currently applied to the view.
bool AllowEdit
Implemented by IList source object.
int Find(string propertyName, object key)
Finds an item in the view
void Insert(int index, T item)
Implemented by IList source object.
bool IsReadOnly
Implemented by IList source object.
bool IsSorted
Gets a value indicating whether the view is currently sorted.
IEnumerator< T > GetEnumerator()
Returns an enumerator for the list, honoring any sort that is active at the time.
ListChangedEventHandler ListChanged
Raised to indicate that the list's data has changed.
SortedBindingList(IList< T > list)
Creates a new view based on the provided IList object.
PropertyDescriptor SortProperty
Returns the PropertyDescriptor of the current sort.
void AddIndex(PropertyDescriptor property)
Implemented by IList source object.
void RemoveIndex(PropertyDescriptor property)
Implemented by IList source object.
ListSortDirection SortDirection
Returns the direction of the current sort.
bool SupportsChangeNotification
Returns true since this object does raise the ListChanged event.
bool SupportsSearching
Implemented by IList source object.
bool AllowNew
Implemented by IList source object.
T[] ToArray()
Get an array containing all items in the list.
bool Remove(T item)
Implemented by IList source object.
IList< T > SourceList
Gets the source list over which this SortedBindingList is a view.
int Count
Implemented by IList source object.
void Clear()
Implemented by IList source object.
bool AllowRemove
Implemented by IList source object.
void OnListChanged(ListChangedEventArgs e)
Raises the ListChanged event.
void Add(T item)
Implemented by IList source object.
bool SupportsSorting
Returns true.
bool Contains(T item)
Implemented by IList source object.
int IndexOf(T item)
Implemented by IList source object.
void ApplySort(PropertyDescriptor property, ListSortDirection direction)
Applies a sort to the view.
void CopyTo(T[] array, int arrayIndex)
Implemented by IList source object.