winform datagridview 绑定泛型集合变得不支持排序的解决方案
案例:
环境:Winform程序
控件:Datagridview
现象:Datagridview控件绑定到List<T>泛型数据上不支持排序
Datagridview控件绑定到DataTable上可以支持排序
结论:泛型会使Datagridview失去排序特性
解决:实现BindingList<T>接口
实现代码:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Linq; 5 using System.Reflection; 6 using System.Text; 7 8 namespace HOET.Plugins.Orders.Model 9 { 10 /// <summary> 11 /// 泛型会失去DataTable特性,DataGridView绑定List<T>后不支持排序 12 /// </summary> 13 /// <typeparam name="T"></typeparam> 14 class SortableBindingList<T> : BindingList<T> 15 { 16 private bool isSortedCore = true; 17 private ListSortDirection sortDirectionCore = ListSortDirection.Ascending; 18 private PropertyDescriptor sortPropertyCore = null; 19 private string defaultSortItem; 20 21 public SortableBindingList() : base() { } 22 23 public SortableBindingList(IList<T> list) : base(list) { } 24 25 protected override bool SupportsSortingCore 26 { 27 get { return true; } 28 } 29 30 protected override bool SupportsSearchingCore 31 { 32 get { return true; } 33 } 34 35 protected override bool IsSortedCore 36 { 37 get { return isSortedCore; } 38 } 39 40 protected override ListSortDirection SortDirectionCore 41 { 42 get { return sortDirectionCore; } 43 } 44 45 protected override PropertyDescriptor SortPropertyCore 46 { 47 get { return sortPropertyCore; } 48 } 49 50 protected override int FindCore(PropertyDescriptor prop, object key) 51 { 52 for(int i = 0; i < this.Count; i++) 53 { 54 if(Equals(prop.GetValue(this[i]),key)) 55 { 56 return i; 57 } 58 } 59 60 return -1; 61 } 62 63 protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction) 64 { 65 isSortedCore = true; 66 sortPropertyCore = prop; 67 sortDirectionCore = direction; 68 Sort(); 69 } 70 71 protected override void RemoveSortCore() 72 { 73 if(isSortedCore) 74 { 75 isSortedCore = false; 76 sortPropertyCore = null; 77 sortDirectionCore = ListSortDirection.Ascending; 78 Sort(); 79 } 80 } 81 82 public string DefaultSortItem 83 { 84 get 85 { 86 return defaultSortItem; 87 } 88 set 89 { 90 if(defaultSortItem != value) 91 { 92 defaultSortItem = value; 93 Sort(); 94 } 95 } 96 } 97 98 private void Sort() 99 { 100 List<T> list = this.Items as List<T>; 101 list.Sort(CompareCore); 102 ResetBindings(); 103 } 104 105 private int CompareCore(T o1, T o2) 106 { 107 int ret = 0; 108 if(SortPropertyCore != null) 109 { 110 ret = CompareValue(SortPropertyCore.GetValue(o1), SortPropertyCore.GetValue(o2), SortPropertyCore.PropertyType); 111 } 112 if(ret == 0 && DefaultSortItem != null) 113 { 114 PropertyInfo property = typeof(T).GetProperty(DefaultSortItem, BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.IgnoreCase, null, null, new Type[0], null); 115 if(property != null) 116 { 117 ret = CompareValue(property.GetValue(o1, null), property.GetValue(o2, null), property.PropertyType); 118 } 119 } 120 if(SortDirectionCore == ListSortDirection.Descending) 121 { 122 ret = -ret; 123 } 124 125 return ret; 126 } 127 128 private static int CompareValue(object o1, object o2, Type type) 129 { 130 if(o1 == null) 131 { 132 return o2 == null ? 0 : -1; 133 } 134 else if(o2 == null) 135 { 136 return 1; 137 } 138 else if(type == typeof(char)) 139 { 140 return String.Compare(o1.ToString().Trim(), o2.ToString().Trim()); 141 } 142 else if (type.IsEnum ||type.IsPrimitive) 143 { 144 return Convert.ToDouble(o1).CompareTo(Convert.ToDouble(o2)); 145 } 146 else if(type == typeof(DateTime)) 147 { 148 return Convert.ToDateTime(o1).CompareTo(o2); 149 } 150 else 151 { 152 return String.Compare(o1.ToString().Trim(), o2.ToString().Trim()); 153 } 154 } 155 } 156 }