9using System.ComponentModel;
10using System.Collections.Generic;
11using System.Collections;
22 IList<T>, IBindingList, IEnumerable<T>,
26 #region ListItem class
28 private class ListItem
31 private int _baseIndex;
40 get {
return _baseIndex; }
41 set { _baseIndex = value; }
44 public ListItem(
object key,
int baseIndex)
47 _baseIndex = baseIndex;
50 public override string ToString()
52 return Key.ToString();
59 #region Filtered enumerator
61 private class FilteredEnumerator : IEnumerator<T>
63 private IList<T> _list;
64 private List<ListItem> _filterIndex;
67 public FilteredEnumerator(
69 List<ListItem> filterIndex)
72 _filterIndex = filterIndex;
78 get {
return _list[_filterIndex[_index].BaseIndex]; }
81 Object System.Collections.IEnumerator.Current
83 get {
return _list[_filterIndex[_index].BaseIndex]; }
86 public bool MoveNext()
88 if (_index < _filterIndex.Count - 1)
102 #region IDisposable Support
104 private bool _disposedValue =
false;
107 protected virtual void Dispose(
bool disposing)
117 _disposedValue =
true;
121 public void Dispose()
125 GC.SuppressFinalize(
this);
128 ~FilteredEnumerator()
139 #region Filter/Unfilter
141 private void DoFilter()
144 _filterIndex.Clear();
146 if (_provider ==
null)
147 _provider = DefaultFilter.Filter;
149 if (_filterBy ==
null)
151 foreach (T obj
in _list)
153 if (_provider.Invoke(obj, _filter))
154 _filterIndex.Add(
new ListItem(obj, index));
160 foreach (T obj
in _list)
162 object tmp = _filterBy.GetValue(obj);
163 if (_provider.Invoke(tmp, _filter))
164 _filterIndex.Add(
new ListItem(tmp, index));
171 OnListChanged(
new ListChangedEventArgs(ListChangedType.Reset, 0));
175 private void UnDoFilter()
177 _filterIndex.Clear();
182 OnListChanged(
new ListChangedEventArgs(ListChangedType.Reset, 0));
188 #region IEnumerable<T>
197 return new FilteredEnumerator(_list, _filterIndex);
199 return _list.GetEnumerator();
204 #region IBindingList, IList<T>
213 if (_supportsBinding)
214 _bindingList.AddIndex(property);
223 if (_supportsBinding)
224 result = (T)_bindingList.AddNew();
239 if (_supportsBinding)
240 return _bindingList.AllowEdit;
253 if (_supportsBinding)
254 return _bindingList.AllowNew;
267 if (_supportsBinding)
268 return _bindingList.AllowRemove;
281 PropertyDescriptor property, ListSortDirection direction)
284 _bindingList.ApplySort(property, direction);
296 string propertyName, ListSortDirection direction)
300 var
property = GetPropertyDescriptor(propertyName);
301 _bindingList.ApplySort(property, direction);
312 private static PropertyDescriptor GetPropertyDescriptor(
string propertyName)
314 PropertyDescriptor
property =
null;
316 if (!String.IsNullOrEmpty(propertyName))
318 Type itemType = typeof(T);
319 foreach (PropertyDescriptor prop
in TypeDescriptor.GetProperties(itemType))
321 if (prop.Name == propertyName)
329 if (property ==
null)
340 public int Find(
string propertyName,
object key)
342 PropertyDescriptor findProperty =
null;
344 if (!String.IsNullOrEmpty(propertyName))
346 Type itemType = typeof(T);
347 foreach (PropertyDescriptor prop
in TypeDescriptor.GetProperties(itemType))
349 if (prop.Name == propertyName)
357 return Find(findProperty, key);
367 public int Find(PropertyDescriptor property,
object key)
369 if (_supportsBinding)
370 return FilteredIndex(_bindingList.Find(property, key));
383 return _bindingList.IsSorted;
417 if (_supportsBinding)
418 _bindingList.RemoveIndex(property);
427 _bindingList.RemoveSort();
440 return _bindingList.SortDirection;
442 return ListSortDirection.Ascending;
454 return _bindingList.SortProperty;
476 if (_supportsBinding)
477 return _bindingList.SupportsSearching;
490 if (_supportsBinding)
491 return _bindingList.SupportsSorting;
503 public void CopyTo(T[] array,
int arrayIndex)
505 int pos = arrayIndex;
506 foreach (T child
in this)
513 void System.Collections.ICollection.CopyTo(System.Array array,
int index)
515 T[] tmp =
new T[array.Length];
517 Array.Copy(tmp, 0, array, index, array.Length);
528 return _filterIndex.Count;
534 bool System.Collections.ICollection.IsSynchronized
536 get {
return false; }
539 object System.Collections.ICollection.SyncRoot
541 get {
return _list; }
544 IEnumerator System.Collections.IEnumerable.GetEnumerator()
558 int System.Collections.IList.Add(
object value)
561 int index = FilteredIndex(_list.Count - 1);
574 for (
int index =
Count - 1; index >= 0; index--)
589 return _list.Contains(item);
592 bool System.Collections.IList.Contains(
object value)
606 return FilteredIndex(_list.IndexOf(item));
609 int System.Collections.IList.IndexOf(
object value)
622 _list.Insert(index, item);
625 void System.Collections.IList.Insert(
int index,
object value)
630 bool System.Collections.IList.IsFixedSize
632 get {
return false; }
641 get {
return _list.IsReadOnly; }
644 object System.Collections.IList.this[
int index]
652 this[index] = (T)value;
664 return _list.Remove(item);
667 void System.Collections.IList.Remove(
object value)
681 _list.RemoveAt(OriginalIndex(index));
684 _list.RemoveAt(index);
693 public T
this[
int index]
699 int src = OriginalIndex(index);
708 _list[OriginalIndex(index)] = value;
710 _list[index] = value;
722 [EditorBrowsable(EditorBrowsableState.Advanced)]
733 private IList<T> _list;
734 private bool _supportsBinding;
735 private IBindingList _bindingList;
736 private bool _filtered;
737 private PropertyDescriptor _filterBy;
738 private object _filter;
740 private List<ListItem> _filterIndex =
741 new List<ListItem>();
751 if (_list is IBindingList)
753 _supportsBinding =
true;
754 _bindingList = (IBindingList)_list;
755 _bindingList.ListChanged +=
756 new ListChangedEventHandler(SourceChanged);
769 _provider = filterProvider;
806 get {
return _filterBy; }
814 get {
return _filtered; }
824 if (_filterBy ==
null || _filter ==
null)
839 if (!String.IsNullOrEmpty(propertyName))
841 Type itemType = typeof(T);
842 foreach (PropertyDescriptor prop
in
843 TypeDescriptor.GetProperties(itemType))
845 if (prop.Name == propertyName)
863 PropertyDescriptor property,
object filter)
865 _filterBy = property;
880 private void SourceChanged(
881 object sender, ListChangedEventArgs e)
886 int filteredIndex = -1;
889 switch (e.ListChangedType)
891 case ListChangedType.ItemAdded:
892 listIndex = e.NewIndex;
894 newItem = _list[listIndex];
895 if (_filterBy !=
null)
896 newKey = _filterBy.GetValue(newItem);
900 new ListItem(newKey, listIndex));
901 filteredIndex = _filterIndex.Count - 1;
904 new ListChangedEventArgs(
905 e.ListChangedType, filteredIndex));
908 case ListChangedType.ItemChanged:
909 listIndex = e.NewIndex;
911 filteredIndex = FilteredIndex(listIndex);
912 if (filteredIndex != -1)
914 newItem = _list[listIndex];
915 if (_filterBy !=
null)
916 newKey = _filterBy.GetValue(newItem);
919 _filterIndex[filteredIndex] =
920 new ListItem(newKey, listIndex);
923 if (filteredIndex > -1)
925 new ListChangedEventArgs(
926 e.ListChangedType, filteredIndex, e.PropertyDescriptor));
929 case ListChangedType.ItemDeleted:
930 listIndex = e.NewIndex;
933 filteredIndex = FilteredIndex(listIndex);
934 if (filteredIndex != -1)
935 _filterIndex.RemoveAt(filteredIndex);
937 foreach (ListItem item
in _filterIndex)
938 if (item.BaseIndex > e.NewIndex)
941 if (filteredIndex > -1)
943 new ListChangedEventArgs(
944 e.ListChangedType, filteredIndex));
947 case ListChangedType.PropertyDescriptorAdded:
948 case ListChangedType.PropertyDescriptorChanged:
949 case ListChangedType.PropertyDescriptorDeleted:
956 new ListChangedEventArgs(
957 ListChangedType.Reset, 0));
965 private int OriginalIndex(
int filteredIndex)
968 return _filterIndex[filteredIndex].BaseIndex;
970 return filteredIndex;
973 private int FilteredIndex(
int originalIndex)
978 for (
int index = 0; index < _filterIndex.Count; index++)
980 if (_filterIndex[index].BaseIndex == originalIndex)
988 result = originalIndex;
992 #region ICancelAddNew Members
1007 void ICancelAddNew.CancelNew(
int itemIndex)
1009 if (itemIndex <= -1)
return;
1011 ICancelAddNew can = _list as ICancelAddNew;
1013 can.CancelNew(OriginalIndex(itemIndex));
1015 _list.RemoveAt(OriginalIndex(itemIndex));
1018 void ICancelAddNew.EndNew(
int itemIndex)
1020 ICancelAddNew can = _list as ICancelAddNew;
1022 can.EndNew(OriginalIndex(itemIndex));
1034 List<T> result =
new List<T>();
1035 foreach (T item
in this)
1037 return result.ToArray();
Provides a filtered view into an existing IList(Of T).
int Find(string propertyName, object key)
Finds an item in the view
void ApplyFilter()
Applies a filter to the view using the most recently used property name and filter provider.
void OnListChanged(ListChangedEventArgs e)
Raises the ListChanged event.
void ApplyFilter(string propertyName, object filter)
Applies a filter to the view.
bool IsFiltered
Returns True if the view is currently filtered.
void RemoveAt(int index)
Removes an item from the list.
bool SupportsSearching
Implemented by IList source object.
void RemoveFilter()
Removes the filter from the list, so the view reflects the state of the original list.
PropertyDescriptor FilterProperty
The property on which the items will be filtered.
ListSortDirection SortDirection
Returns the direction of the current sort.
void Clear()
Clears the list.
void RemoveIndex(PropertyDescriptor property)
Implemented by IList source object.
void Insert(int index, T item)
Inserts an item into the list.
T[] ToArray()
Get an array containing all items in the list.
IList< T > SourceList
Gets the source list over which this SortedBindingList is a view.
bool SupportsSorting
Returns True.
IEnumerator< T > GetEnumerator()
Gets an enumerator object.
bool AllowEdit
Implemented by IList source object.
bool AllowRemove
Implemented by IList source object.
bool IsReadOnly
Gets a value indicating whether the list is read-only.
void Add(T item)
Adds an item to the list.
void ApplySort(string propertyName, ListSortDirection direction)
Sorts the list if the original list supports sorting.
void AddIndex(PropertyDescriptor property)
Implemented by IList source object.
ListChangedEventHandler ListChanged
Raised to indicate that the list's data has changed.
void RemoveSort()
Removes any sort currently applied to the view.
bool Contains(T item)
Determines whether the specified item is contained in the list.
bool Remove(T item)
Removes an item from the list.
void CopyTo(T[] array, int arrayIndex)
Copies the contents of the list to an array.
int IndexOf(T item)
Gets the 0-based index of an item in the list.
bool SupportsChangeNotification
Returns True since this object does raise the ListChanged event.
PropertyDescriptor SortProperty
Returns the PropertyDescriptor of the current sort.
object AddNew()
Implemented by IList source object.
FilteredBindingList(IList< T > list, FilterProvider filterProvider)
Creates a new view based on the provided IList object.
int Count
Gets the number of items in the list.
FilterProvider FilterProvider
Gets or sets the filter provider method.
void ApplyFilter(PropertyDescriptor property, object filter)
Applies a filter to the view.
void ApplySort(PropertyDescriptor property, ListSortDirection direction)
Sorts the list if the original list supports sorting.
int Find(PropertyDescriptor property, object key)
Implemented by IList source object.
bool IsSorted
Returns True if the view is currently sorted.
bool AllowNew
Implemented by IList source object.
FilteredBindingList(IList< T > list)
Creates a new view based on the provided IList object.
A strongly-typed resource class, for looking up localized strings, etc.
static string SortingNotSupported
Looks up a localized string similar to Sorting not supported.
static string FilterRequiredException
Looks up a localized string similar to Filter parameter and filter provider are required.
static string SortedBindingListPropertyNameNotFound
Looks up a localized string similar to PropertyName '{0}' not found in list.