Advertisement
Guest User

Untitled

a guest
Apr 28th, 2017
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 13.58 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Reflection;
  5. using System.Text;
  6. using System.Text.RegularExpressions;
  7.  
  8. namespace TourApp
  9. {
  10.     public class SortableBindingList<T> : BindingList<T>, IBindingListView
  11.     {
  12.         private readonly Dictionary<Type, PropertyComparer<T>> comparers;
  13.         private bool isSorted;
  14.         private ListSortDirection listSortDirection;
  15.         private PropertyDescriptor propertyDescriptor;
  16.         private List<T> originalListValue = new List<T>();
  17.         public List<T> OriginalList
  18.         {
  19.             get
  20.             { return originalListValue; }
  21.         }
  22.  
  23.         public SortableBindingList()
  24.             : base(new List<T>())
  25.         {
  26.             this.comparers = new Dictionary<Type, PropertyComparer<T>>();
  27.         }
  28.  
  29.         public SortableBindingList(IEnumerable<T> enumeration)
  30.             : base(new List<T>(enumeration))
  31.         {
  32.             this.comparers = new Dictionary<Type, PropertyComparer<T>>();
  33.         }
  34.  
  35.         #region Sorting
  36.         System.Collections.ArrayList sortedList;
  37.         SortableBindingList<T> unsortedItems;
  38.         bool isSortedValue;
  39.         ListSortDirection sortDirectionValue;
  40.         PropertyDescriptor sortPropertyValue;
  41.         protected override int FindCore(PropertyDescriptor prop, object key)
  42.         {
  43.  
  44.             PropertyInfo propInfo = typeof(T).GetProperty(prop.Name);
  45.             T item;
  46.  
  47.             if (key != null)
  48.             {
  49.  
  50.                 for (int i = 0; i < Count; ++i)
  51.                 {
  52.                     item = (T)Items[i];
  53.                     if (propInfo.GetValue(item, null).Equals(key))
  54.                         return i;
  55.                 }
  56.             }
  57.             return -1;
  58.         }
  59.  
  60.         public int Find(string property, object key)
  61.         {
  62.  
  63.             PropertyDescriptorCollection properties =
  64.                 TypeDescriptor.GetProperties(typeof(T));
  65.             PropertyDescriptor prop = properties.Find(property, true);
  66.  
  67.  
  68.             if (prop == null)
  69.                 return -1;
  70.             else
  71.                 return FindCore(prop, key);
  72.         }
  73.  
  74.         protected override bool SupportsSortingCore
  75.         {
  76.             get { return true; }
  77.         }
  78.  
  79.         protected override bool IsSortedCore
  80.         {
  81.             get { return isSortedValue; }
  82.         }
  83.  
  84.         protected override PropertyDescriptor SortPropertyCore
  85.         {
  86.             get { return sortPropertyValue; }
  87.         }
  88.  
  89.         protected override ListSortDirection SortDirectionCore
  90.         {
  91.             get { return sortDirectionValue; }
  92.         }
  93.  
  94.  
  95.         public void ApplySort(string propertyName, ListSortDirection direction)
  96.         {
  97.  
  98.             PropertyDescriptor prop = TypeDescriptor.GetProperties(typeof(T))[propertyName];
  99.  
  100.             if (prop == null)
  101.                 throw new ArgumentException(propertyName +
  102.                     " is not a valid property for type:" + typeof(T).Name);
  103.             else
  104.                 ApplySortCore(prop, direction);
  105.         }
  106.  
  107.         protected override void ApplySortCore(PropertyDescriptor prop,
  108.             ListSortDirection direction)
  109.         {
  110.  
  111.             sortedList = new System.Collections.ArrayList();
  112.  
  113.  
  114.             Type interfaceType = prop.PropertyType.GetInterface("IComparable");
  115.  
  116.             if (interfaceType != null)
  117.             {
  118.  
  119.                 sortPropertyValue = prop;
  120.                 sortDirectionValue = direction;
  121.  
  122.                 unsortedItems = new SortableBindingList<T>();
  123.  
  124.                 if (sortPropertyValue != null)
  125.                 {
  126.  
  127.                     foreach (Object item in this.Items)
  128.                     {
  129.                         unsortedItems.Add((T)item);
  130.                         sortedList.Add(prop.GetValue(item));
  131.                     }
  132.                 }
  133.  
  134.                 sortedList.Sort();
  135.                 T temp;
  136.  
  137.  
  138.                 if (direction == ListSortDirection.Descending)
  139.                     sortedList.Reverse();
  140.  
  141.                 for (int i = 0; i < this.Count; i++)
  142.                 {
  143.                     int position = Find(prop.Name, sortedList[i]);
  144.                     if (position != i && position > 0)
  145.                     {
  146.                         temp = this[i];
  147.                         this[i] = this[position];
  148.                         this[position] = temp;
  149.                     }
  150.                 }
  151.  
  152.                 isSortedValue = true;
  153.  
  154.                 if (String.IsNullOrEmpty(Filter))
  155.                     OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
  156.             }
  157.             else
  158.  
  159.                 throw new InvalidOperationException("Cannot sort by "
  160.                     + prop.Name + ". This" + prop.PropertyType.ToString() +
  161.                     " does not implement IComparable");
  162.         }
  163.  
  164.         protected override void RemoveSortCore()
  165.         {
  166.             this.RaiseListChangedEvents = false;
  167.  
  168.             if (unsortedItems != null && originalListValue.Count > 0)
  169.             {
  170.                 this.Clear();
  171.                 if (Filter != null)
  172.                 {
  173.                     unsortedItems.Filter = this.Filter;
  174.                     foreach (T item in unsortedItems)
  175.                         this.Add(item);
  176.                 }
  177.                 else
  178.                 {
  179.                     foreach (T item in originalListValue)
  180.                         this.Add(item);
  181.                 }
  182.                 isSortedValue = false;
  183.                 this.RaiseListChangedEvents = true;
  184.  
  185.                 OnListChanged(new ListChangedEventArgs(ListChangedType.Reset,
  186.                     -1));
  187.             }
  188.         }
  189.  
  190.         public void RemoveSort()
  191.         {
  192.             RemoveSortCore();
  193.         }
  194.  
  195.  
  196.         public override void EndNew(int itemIndex)
  197.         {
  198.  
  199.             if (IsSortedCore && itemIndex > 0
  200.                 && itemIndex == this.Count - 1)
  201.             {
  202.                 ApplySortCore(this.sortPropertyValue,
  203.                     this.sortDirectionValue);
  204.                 base.EndNew(itemIndex);
  205.             }
  206.         }
  207.  
  208.         #endregion Sorting
  209.  
  210.  
  211.         private string filterValue = null;
  212.  
  213.         public string Filter
  214.         {
  215.             get
  216.             {
  217.                 return filterValue;
  218.             }
  219.             set
  220.             {
  221.                 if (filterValue == value) return;
  222.  
  223.  
  224.                 if (!string.IsNullOrEmpty(value) &&
  225.                     !Regex.IsMatch(value,
  226.                     BuildRegExForFilterFormat(), RegexOptions.Singleline))
  227.                 {
  228.                     throw new ArgumentException("Filter is not in " +
  229.                           "the format: propName[<>=]'value'.");
  230.                 }
  231.  
  232.                 RaiseListChangedEvents = false;
  233.  
  234.                 if (string.IsNullOrEmpty(value))
  235.                     ResetList();
  236.                 else
  237.                 {
  238.                     int count = 0;
  239.                     string[] matches = value.Split(new string[] { " AND " },
  240.                         StringSplitOptions.RemoveEmptyEntries);
  241.  
  242.                     while (count < matches.Length)
  243.                     {
  244.                         string filterPart = matches[count].ToString();
  245.  
  246.  
  247.                         if (!String.IsNullOrEmpty(filterValue)
  248.                                 && !value.Contains(filterValue))
  249.                             ResetList();
  250.  
  251.  
  252.                         SingleFilterInfo filterInfo = ParseFilter(filterPart);
  253.                         ApplyFilter(filterInfo);
  254.                         count++;
  255.                     }
  256.                 }
  257.  
  258.                 filterValue = value;
  259.                 RaiseListChangedEvents = true;
  260.                 OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
  261.             }
  262.         }
  263.  
  264.         internal void ApplyFilter(SingleFilterInfo filterParts)
  265.         {
  266.             List<T> results;
  267.  
  268.  
  269.             Type interfaceType =
  270.                 TypeDescriptor.GetProperties(typeof(T))[filterParts.PropName]
  271.                 .PropertyType.GetInterface("IComparable");
  272.  
  273.             if (interfaceType == null)
  274.                 throw new InvalidOperationException("Filtered property" +
  275.                 " must implement IComparable.");
  276.  
  277.             results = new List<T>();
  278.  
  279.             foreach (T item in this)
  280.             {
  281.                 if (filterParts.PropDesc.GetValue(item) != null)
  282.                 {
  283.                     IComparable compareValue =
  284.                         filterParts.PropDesc.GetValue(item) as IComparable;
  285.                     int result =
  286.                         compareValue.CompareTo(filterParts.CompareValue);
  287.                     if (filterParts.OperatorValue ==
  288.                         FilterOperator.EqualTo && result == 0)
  289.                         results.Add(item);
  290.                     if (filterParts.OperatorValue ==
  291.                         FilterOperator.GreaterThan && result > 0)
  292.                         results.Add(item);
  293.                     if (filterParts.OperatorValue ==
  294.                         FilterOperator.LessThan && result < 0)
  295.                         results.Add(item);
  296.                 }
  297.             }
  298.             this.ClearItems();
  299.             foreach (T itemFound in results)
  300.                 this.Add(itemFound);
  301.         }
  302.         internal SingleFilterInfo ParseFilter(string filterPart)
  303.         {
  304.             SingleFilterInfo filterInfo = new SingleFilterInfo();
  305.             filterInfo.OperatorValue = DetermineFilterOperator(filterPart);
  306.  
  307.             string[] filterStringParts =
  308.                 filterPart.Split(new char[] { (char)filterInfo.OperatorValue });
  309.  
  310.             filterInfo.PropName =
  311.                 filterStringParts[0].Replace("[", "").
  312.                 Replace("]", "").Replace(" AND ", "").Trim();
  313.  
  314.  
  315.             PropertyDescriptor filterPropDesc =
  316.                 TypeDescriptor.GetProperties(typeof(T))[filterInfo.PropName];
  317.  
  318.             filterInfo.PropDesc = filterPropDesc ?? throw new InvalidOperationException("Specified property to " +
  319.                     "filter " + filterInfo.PropName +
  320.                     " on does not exist on type: " + typeof(T).Name);
  321.  
  322.             string comparePartNoQuotes = StripOffQuotes(filterStringParts[1]);
  323.             try
  324.             {
  325.                 TypeConverter converter =
  326.                     TypeDescriptor.GetConverter(filterPropDesc.PropertyType);
  327.  
  328.                 filterInfo.CompareValue =
  329.                     converter.ConvertFromString(comparePartNoQuotes);
  330.             }
  331.             catch (NotSupportedException)
  332.             {
  333.                 throw new InvalidOperationException(
  334.                    filterPropDesc.PropertyType.ToString());
  335.             }
  336.  
  337.             return filterInfo;
  338.         }
  339.         internal FilterOperator DetermineFilterOperator(string filterPart)
  340.         {
  341.  
  342.             if (Regex.IsMatch(filterPart, "[^>^<]="))
  343.                 return FilterOperator.EqualTo;
  344.             else if (Regex.IsMatch(filterPart, "<[^>^=]"))
  345.                 return FilterOperator.LessThan;
  346.             else if (Regex.IsMatch(filterPart, "[^<]>[^=]"))
  347.                 return FilterOperator.GreaterThan;
  348.             else
  349.                 return FilterOperator.None;
  350.         }
  351.         internal static string StripOffQuotes(string filterPart)
  352.         {
  353.  
  354.             if (Regex.IsMatch(filterPart, "'.+'"))
  355.             {
  356.                 int quote = filterPart.IndexOf('\'');
  357.                 filterPart = filterPart.Remove(quote, 1);
  358.                 quote = filterPart.LastIndexOf('\'');
  359.                 filterPart = filterPart.Remove(quote, 1);
  360.                 filterPart = filterPart.Trim();
  361.             }
  362.             return filterPart;
  363.         }
  364.         public static string BuildRegExForFilterFormat()
  365.         {
  366.             StringBuilder regex = new StringBuilder();
  367.  
  368.  
  369.             regex.Append(@"\[?[\w\s]+\]?\s?");
  370.  
  371.             regex.Append(@"[><=]");
  372.  
  373.  
  374.             regex.Append(@"\s?'?.+'?");
  375.  
  376.             return regex.ToString();
  377.         }
  378.  
  379.         private void ResetList()
  380.         {
  381.             this.ClearItems();
  382.             foreach (T t in originalListValue)
  383.                 this.Items.Add(t);
  384.             if (IsSortedCore)
  385.                 ApplySortCore(SortPropertyCore, SortDirectionCore);
  386.         }
  387.  
  388.         protected override void OnListChanged(ListChangedEventArgs e)
  389.         {
  390.  
  391.             if (e.ListChangedType == ListChangedType.Reset)
  392.             {
  393.                 if (Filter == null || Filter == "")
  394.                     AllowNew = true;
  395.                 else
  396.                     AllowNew = false;
  397.             }
  398.  
  399.             if (e.ListChangedType == ListChangedType.ItemAdded)
  400.             {
  401.                 OriginalList.Add(this[e.NewIndex]);
  402.                 if (!String.IsNullOrEmpty(Filter))
  403.  
  404.                 {
  405.                     string cachedFilter = this.Filter;
  406.                     this.Filter = "";
  407.                     this.Filter = cachedFilter;
  408.                 }
  409.             }
  410.  
  411.             if (e.ListChangedType == ListChangedType.ItemDeleted)
  412.                 OriginalList.RemoveAt(e.NewIndex);
  413.  
  414.             base.OnListChanged(e);
  415.         }
  416.  
  417.  
  418.  
  419.         public bool SupportsFiltering => true;
  420.  
  421.         public ListSortDescriptionCollection SortDescriptions => throw new NotImplementedException();
  422.  
  423.         public bool SupportsAdvancedSorting => throw new NotImplementedException();
  424.  
  425.         public void RemoveFilter()
  426.         {
  427.             throw new NotImplementedException();
  428.         }
  429.  
  430.         public void ApplySort(ListSortDescriptionCollection sorts)
  431.         {
  432.             throw new NotImplementedException();
  433.         }
  434.     }
  435. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement