PageRenderTime 67ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/referencesource/System.Data.Linq/SortableBindingList.cs

http://github.com/mono/mono
C# | 121 lines | 92 code | 17 blank | 12 comment | 18 complexity | e7888ca5d34eae40f3ffbbc6fd460e0a MD5 | raw file
Possible License(s): GPL-2.0, CC-BY-SA-3.0, LGPL-2.0, MPL-2.0-no-copyleft-exception, LGPL-2.1, Unlicense, Apache-2.0
  1. using System;
  2. using System.Linq;
  3. using System.Collections.Generic;
  4. using System.Text;
  5. using System.ComponentModel;
  6. using System.Linq.Expressions;
  7. using System.Collections;
  8. using System.Reflection;
  9. using System.Xml.Linq;
  10. namespace System.Data.Linq
  11. {
  12. /// <summary>
  13. /// Adds sorting feature to BindingList<T>
  14. /// </summary>
  15. /// <typeparam name="T"></typeparam>
  16. internal class SortableBindingList<T> : BindingList<T> {
  17. internal SortableBindingList(IList<T> list) : base(list) { }
  18. private bool isSorted = false;
  19. private PropertyDescriptor sortProperty = null;
  20. private ListSortDirection sortDirection = ListSortDirection.Ascending;
  21. protected override void RemoveSortCore() {
  22. isSorted = false;
  23. sortProperty = null;
  24. }
  25. protected override ListSortDirection SortDirectionCore {
  26. get { return sortDirection; }
  27. }
  28. protected override PropertyDescriptor SortPropertyCore {
  29. get { return sortProperty; }
  30. }
  31. protected override bool IsSortedCore {
  32. get { return isSorted; }
  33. }
  34. protected override bool SupportsSortingCore {
  35. get { return true; }
  36. }
  37. protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction) {
  38. //Only apply sort if the column is sortable, decision was made not to throw in this case.
  39. //Don't prevent nullable types from working.
  40. Type propertyType = prop.PropertyType;
  41. if (PropertyComparer.IsAllowable(propertyType))
  42. {
  43. ((List<T>)this.Items).Sort(new PropertyComparer(prop, direction));
  44. sortDirection = direction;
  45. sortProperty = prop;
  46. isSorted = true;
  47. OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
  48. }
  49. }
  50. internal class PropertyComparer : Comparer<T> {
  51. private PropertyDescriptor prop;
  52. private IComparer comparer;
  53. private ListSortDirection direction;
  54. private bool useToString;
  55. internal PropertyComparer(PropertyDescriptor prop, ListSortDirection direction) {
  56. if (prop.ComponentType != typeof(T)) {
  57. throw new MissingMemberException(typeof(T).Name, prop.Name);
  58. }
  59. this.prop = prop;
  60. this.direction = direction;
  61. if (OkWithIComparable(prop.PropertyType)) {
  62. Type comparerType = typeof(Comparer<>).MakeGenericType(prop.PropertyType);
  63. PropertyInfo defaultComparer = comparerType.GetProperty("Default");
  64. comparer = (IComparer)defaultComparer.GetValue(null, null);
  65. useToString = false;
  66. }
  67. else if (OkWithToString(prop.PropertyType)) {
  68. comparer = StringComparer.CurrentCultureIgnoreCase;
  69. useToString = true;
  70. }
  71. }
  72. public override int Compare(T x, T y) {
  73. object xValue = prop.GetValue(x);
  74. object yValue = prop.GetValue(y);
  75. if (useToString) {
  76. xValue = xValue != null ? xValue.ToString() : null;
  77. yValue = yValue != null ? yValue.ToString() : null;
  78. }
  79. if (direction == ListSortDirection.Ascending) {
  80. return comparer.Compare(xValue, yValue);
  81. }
  82. else {
  83. return comparer.Compare(yValue, xValue);
  84. }
  85. }
  86. protected static bool OkWithToString(Type t) {
  87. // this is the list of types that behave specially for the purpose of
  88. // sorting. if we have a property of this type, and it does not implement
  89. // IComparable, then this class will sort the properties according to the
  90. // ToString() method.
  91. // In the case of an XNode, the ToString() returns the
  92. // XML, which is what we care about.
  93. return (t.Equals(typeof(XNode)) || t.IsSubclassOf(typeof(XNode)));
  94. }
  95. protected static bool OkWithIComparable(Type t) {
  96. return (t.GetInterface("IComparable") != null)
  97. || (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>));
  98. }
  99. public static bool IsAllowable(Type t) {
  100. return OkWithToString(t) || OkWithIComparable(t);
  101. }
  102. }
  103. }
  104. }