Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Reflection;
- using System.Text;
- using System.Text.RegularExpressions;
- namespace TourApp
- {
- public class SortableBindingList<T> : BindingList<T>, IBindingListView
- {
- private readonly Dictionary<Type, PropertyComparer<T>> comparers;
- private bool isSorted;
- private ListSortDirection listSortDirection;
- private PropertyDescriptor propertyDescriptor;
- private List<T> originalListValue = new List<T>();
- public List<T> OriginalList
- {
- get
- { return originalListValue; }
- }
- public SortableBindingList()
- : base(new List<T>())
- {
- this.comparers = new Dictionary<Type, PropertyComparer<T>>();
- }
- public SortableBindingList(IEnumerable<T> enumeration)
- : base(new List<T>(enumeration))
- {
- this.comparers = new Dictionary<Type, PropertyComparer<T>>();
- }
- #region Sorting
- System.Collections.ArrayList sortedList;
- SortableBindingList<T> unsortedItems;
- bool isSortedValue;
- ListSortDirection sortDirectionValue;
- PropertyDescriptor sortPropertyValue;
- protected override int FindCore(PropertyDescriptor prop, object key)
- {
- PropertyInfo propInfo = typeof(T).GetProperty(prop.Name);
- T item;
- if (key != null)
- {
- for (int i = 0; i < Count; ++i)
- {
- item = (T)Items[i];
- if (propInfo.GetValue(item, null).Equals(key))
- return i;
- }
- }
- return -1;
- }
- public int Find(string property, object key)
- {
- PropertyDescriptorCollection properties =
- TypeDescriptor.GetProperties(typeof(T));
- PropertyDescriptor prop = properties.Find(property, true);
- if (prop == null)
- return -1;
- else
- return FindCore(prop, key);
- }
- protected override bool SupportsSortingCore
- {
- get { return true; }
- }
- protected override bool IsSortedCore
- {
- get { return isSortedValue; }
- }
- protected override PropertyDescriptor SortPropertyCore
- {
- get { return sortPropertyValue; }
- }
- protected override ListSortDirection SortDirectionCore
- {
- get { return sortDirectionValue; }
- }
- public void ApplySort(string propertyName, ListSortDirection direction)
- {
- PropertyDescriptor prop = TypeDescriptor.GetProperties(typeof(T))[propertyName];
- if (prop == null)
- throw new ArgumentException(propertyName +
- " is not a valid property for type:" + typeof(T).Name);
- else
- ApplySortCore(prop, direction);
- }
- protected override void ApplySortCore(PropertyDescriptor prop,
- ListSortDirection direction)
- {
- sortedList = new System.Collections.ArrayList();
- Type interfaceType = prop.PropertyType.GetInterface("IComparable");
- if (interfaceType != null)
- {
- sortPropertyValue = prop;
- sortDirectionValue = direction;
- unsortedItems = new SortableBindingList<T>();
- if (sortPropertyValue != null)
- {
- foreach (Object item in this.Items)
- {
- unsortedItems.Add((T)item);
- sortedList.Add(prop.GetValue(item));
- }
- }
- sortedList.Sort();
- T temp;
- if (direction == ListSortDirection.Descending)
- sortedList.Reverse();
- for (int i = 0; i < this.Count; i++)
- {
- int position = Find(prop.Name, sortedList[i]);
- if (position != i && position > 0)
- {
- temp = this[i];
- this[i] = this[position];
- this[position] = temp;
- }
- }
- isSortedValue = true;
- if (String.IsNullOrEmpty(Filter))
- OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
- }
- else
- throw new InvalidOperationException("Cannot sort by "
- + prop.Name + ". This" + prop.PropertyType.ToString() +
- " does not implement IComparable");
- }
- protected override void RemoveSortCore()
- {
- this.RaiseListChangedEvents = false;
- if (unsortedItems != null && originalListValue.Count > 0)
- {
- this.Clear();
- if (Filter != null)
- {
- unsortedItems.Filter = this.Filter;
- foreach (T item in unsortedItems)
- this.Add(item);
- }
- else
- {
- foreach (T item in originalListValue)
- this.Add(item);
- }
- isSortedValue = false;
- this.RaiseListChangedEvents = true;
- OnListChanged(new ListChangedEventArgs(ListChangedType.Reset,
- -1));
- }
- }
- public void RemoveSort()
- {
- RemoveSortCore();
- }
- public override void EndNew(int itemIndex)
- {
- if (IsSortedCore && itemIndex > 0
- && itemIndex == this.Count - 1)
- {
- ApplySortCore(this.sortPropertyValue,
- this.sortDirectionValue);
- base.EndNew(itemIndex);
- }
- }
- #endregion Sorting
- private string filterValue = null;
- public string Filter
- {
- get
- {
- return filterValue;
- }
- set
- {
- if (filterValue == value) return;
- if (!string.IsNullOrEmpty(value) &&
- !Regex.IsMatch(value,
- BuildRegExForFilterFormat(), RegexOptions.Singleline))
- {
- throw new ArgumentException("Filter is not in " +
- "the format: propName[<>=]'value'.");
- }
- RaiseListChangedEvents = false;
- if (string.IsNullOrEmpty(value))
- ResetList();
- else
- {
- int count = 0;
- string[] matches = value.Split(new string[] { " AND " },
- StringSplitOptions.RemoveEmptyEntries);
- while (count < matches.Length)
- {
- string filterPart = matches[count].ToString();
- if (!String.IsNullOrEmpty(filterValue)
- && !value.Contains(filterValue))
- ResetList();
- SingleFilterInfo filterInfo = ParseFilter(filterPart);
- ApplyFilter(filterInfo);
- count++;
- }
- }
- filterValue = value;
- RaiseListChangedEvents = true;
- OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
- }
- }
- internal void ApplyFilter(SingleFilterInfo filterParts)
- {
- List<T> results;
- Type interfaceType =
- TypeDescriptor.GetProperties(typeof(T))[filterParts.PropName]
- .PropertyType.GetInterface("IComparable");
- if (interfaceType == null)
- throw new InvalidOperationException("Filtered property" +
- " must implement IComparable.");
- results = new List<T>();
- foreach (T item in this)
- {
- if (filterParts.PropDesc.GetValue(item) != null)
- {
- IComparable compareValue =
- filterParts.PropDesc.GetValue(item) as IComparable;
- int result =
- compareValue.CompareTo(filterParts.CompareValue);
- if (filterParts.OperatorValue ==
- FilterOperator.EqualTo && result == 0)
- results.Add(item);
- if (filterParts.OperatorValue ==
- FilterOperator.GreaterThan && result > 0)
- results.Add(item);
- if (filterParts.OperatorValue ==
- FilterOperator.LessThan && result < 0)
- results.Add(item);
- }
- }
- this.ClearItems();
- foreach (T itemFound in results)
- this.Add(itemFound);
- }
- internal SingleFilterInfo ParseFilter(string filterPart)
- {
- SingleFilterInfo filterInfo = new SingleFilterInfo();
- filterInfo.OperatorValue = DetermineFilterOperator(filterPart);
- string[] filterStringParts =
- filterPart.Split(new char[] { (char)filterInfo.OperatorValue });
- filterInfo.PropName =
- filterStringParts[0].Replace("[", "").
- Replace("]", "").Replace(" AND ", "").Trim();
- PropertyDescriptor filterPropDesc =
- TypeDescriptor.GetProperties(typeof(T))[filterInfo.PropName];
- filterInfo.PropDesc = filterPropDesc ?? throw new InvalidOperationException("Specified property to " +
- "filter " + filterInfo.PropName +
- " on does not exist on type: " + typeof(T).Name);
- string comparePartNoQuotes = StripOffQuotes(filterStringParts[1]);
- try
- {
- TypeConverter converter =
- TypeDescriptor.GetConverter(filterPropDesc.PropertyType);
- filterInfo.CompareValue =
- converter.ConvertFromString(comparePartNoQuotes);
- }
- catch (NotSupportedException)
- {
- throw new InvalidOperationException(
- filterPropDesc.PropertyType.ToString());
- }
- return filterInfo;
- }
- internal FilterOperator DetermineFilterOperator(string filterPart)
- {
- if (Regex.IsMatch(filterPart, "[^>^<]="))
- return FilterOperator.EqualTo;
- else if (Regex.IsMatch(filterPart, "<[^>^=]"))
- return FilterOperator.LessThan;
- else if (Regex.IsMatch(filterPart, "[^<]>[^=]"))
- return FilterOperator.GreaterThan;
- else
- return FilterOperator.None;
- }
- internal static string StripOffQuotes(string filterPart)
- {
- if (Regex.IsMatch(filterPart, "'.+'"))
- {
- int quote = filterPart.IndexOf('\'');
- filterPart = filterPart.Remove(quote, 1);
- quote = filterPart.LastIndexOf('\'');
- filterPart = filterPart.Remove(quote, 1);
- filterPart = filterPart.Trim();
- }
- return filterPart;
- }
- public static string BuildRegExForFilterFormat()
- {
- StringBuilder regex = new StringBuilder();
- regex.Append(@"\[?[\w\s]+\]?\s?");
- regex.Append(@"[><=]");
- regex.Append(@"\s?'?.+'?");
- return regex.ToString();
- }
- private void ResetList()
- {
- this.ClearItems();
- foreach (T t in originalListValue)
- this.Items.Add(t);
- if (IsSortedCore)
- ApplySortCore(SortPropertyCore, SortDirectionCore);
- }
- protected override void OnListChanged(ListChangedEventArgs e)
- {
- if (e.ListChangedType == ListChangedType.Reset)
- {
- if (Filter == null || Filter == "")
- AllowNew = true;
- else
- AllowNew = false;
- }
- if (e.ListChangedType == ListChangedType.ItemAdded)
- {
- OriginalList.Add(this[e.NewIndex]);
- if (!String.IsNullOrEmpty(Filter))
- {
- string cachedFilter = this.Filter;
- this.Filter = "";
- this.Filter = cachedFilter;
- }
- }
- if (e.ListChangedType == ListChangedType.ItemDeleted)
- OriginalList.RemoveAt(e.NewIndex);
- base.OnListChanged(e);
- }
- public bool SupportsFiltering => true;
- public ListSortDescriptionCollection SortDescriptions => throw new NotImplementedException();
- public bool SupportsAdvancedSorting => throw new NotImplementedException();
- public void RemoveFilter()
- {
- throw new NotImplementedException();
- }
- public void ApplySort(ListSortDescriptionCollection sorts)
- {
- throw new NotImplementedException();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement