关于PropertyGrid控件的排序问题
前些天,由于在项目中需要用到PropertyGrid这个控件,展现其所在控件的某些属性,由于有些控件的属性较多,不易浏览,而且PropertyGrid的排序默认的按照字母的顺序排列的,这样导致在在某些属性想要排在第一位非常不方便,于是我总结了网友们的一些思路,自己便解决呢!现在来说说解决思路:
1.首先为PropertyGrid添加SelectedObjectsChanged事件!
1 private void propertyGrid_flow_SelectedObjectsChanged(object sender, EventArgs e) 2 { 3 propertyGrid_flow.Tag = propertyGrid_flow.PropertySort; 4 propertyGrid_flow.PropertySort = PropertySort.CategorizedAlphabetical; 5 propertyGrid_flow.Paint += new PaintEventHandler(propertyGrid_flow_Paint); 6 }
2.为PropertyGrid添加Paint事件! 这其中就是最核心的代码,就是按照propertyGrid默认属性排序!
1 var categorysinfo = propertyGrid_flow.SelectedObject.GetType().GetField("categorys", BindingFlags.NonPublic | BindingFlags.Instance); 2 if (categorysinfo != null) 3 { 4 var categorys = categorysinfo.GetValue(propertyGrid_flow.SelectedObject) as List<String>; 5 propertyGrid_flow.CollapseAllGridItems(); 6 GridItemCollection currentPropEntries = propertyGrid_flow.GetType().GetField("currentPropEntries", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(propertyGrid_flow) as GridItemCollection; 7 var newarray = currentPropEntries.Cast<GridItem>().OrderBy((t) => categorys.IndexOf(t.Label)).ToArray(); 8 currentPropEntries.GetType().GetField("entries", BindingFlags.NonPublic | BindingFlags.Instance).SetValue(currentPropEntries, newarray); 9 propertyGrid_flow.ExpandAllGridItems(); 10 propertyGrid_flow.PropertySort = (PropertySort)propertyGrid_flow.Tag; 11 } 12 propertyGrid_flow.Paint -= new PaintEventHandler(propertyGrid_flow_Paint);
3.在其中可以看到有个“categorys”变量,其中是是在propertyGrid的属性中命名:
[TypeConverter(typeof(PropertySorter))]
public class UctlNodeStepProperty : PropertyGird
{
private List<string> categorys = new List<string>(){ "A", "B", "C", "D" };
}
4. 罗列propertyGrid的属性:
1 private string _a1=""; 2 private string _a2=""; 3 private string _a3=""; 4 private string _b1=""; 5 private string _c1=""; 6 private string _d1=""; 7 8 9 [Browsable(true), Category("A"), ShowChinese("描述"),PropertyOrder(1)] 10 public string A1 11 { 12 get { return _a1; } 13 set { _a1 = value; } 14 } 15 [Browsable(true), Category("A"), ShowChinese("描述"),PropertyOrder(2)] 16 public string A2 17 { 18 get { return _a2; } 19 set { _a2 = value; } 20 } 21 [Browsable(true), Category("A"), ShowChinese("描述"),PropertyOrder(3)] 22 public string A3 23 { 24 get { return _a3; } 25 set { _a3 = value; } 26 } 27 [Browsable(true), Category("B"), ShowChinese("描述")] 28 public string B1 29 { 30 get { return _b1; } 31 set { _b1 = value; } 32 } 33 [Browsable(true), Category("C"), ShowChinese("描述")] 34 public string C1 35 { 36 get { return _c1; } 37 set { _c1 = value; } 38 } 39 [Browsable(true), Category("D"), ShowChinese("描述")] 40 public string D1 41 { 42 get { return _d1; } 43 set { _d1 = value; } 44 }
5.我想大家也看到了其中的代码,其中有个属性“PropertyOrder”,下面就是PropertyOtder类的代码:
1 public class PropertySorter : ExpandableObjectConverter 2 { 3 #region Methods 4 public override bool GetPropertiesSupported(ITypeDescriptorContext context) 5 { 6 return true; 7 } 8 9 public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes) 10 { 11 // 12 // This override returns a list of properties in order 13 // 14 PropertyDescriptorCollection pdc = TypeDescriptor.GetProperties(value, attributes); 15 ArrayList orderedProperties = new ArrayList(); 16 foreach (PropertyDescriptor pd in pdc) 17 { 18 Attribute attribute = pd.Attributes[typeof(PropertyOrderAttribute)]; 19 if (attribute != null) 20 { 21 // 22 // If the attribute is found, then create an pair object to hold it 23 // 24 PropertyOrderAttribute poa = (PropertyOrderAttribute)attribute; 25 orderedProperties.Add(new PropertyOrderPair(pd.Name,poa.Order)); 26 } 27 else 28 { 29 // 30 // If no order attribute is specifed then given it an order of 0 31 // 32 orderedProperties.Add(new PropertyOrderPair(pd.Name,0)); 33 } 34 } 35 // 36 // Perform the actual order using the value PropertyOrderPair classes 37 // implementation of IComparable to sort 38 // 39 orderedProperties.Sort(); 40 41 42 // 43 // Build a string list of the ordered names 44 // 45 ArrayList propertyNames = new ArrayList(); 46 foreach (PropertyOrderPair pop in orderedProperties) 47 { 48 propertyNames.Add(pop.Name); 49 } 50 // 51 // Pass in the ordered list for the PropertyDescriptorCollection to sort by 52 // 53 return pdc.Sort((string[])propertyNames.ToArray(typeof(string))); 54 } 55 #endregion 56 } 57 58 #region Helper Class - PropertyOrderAttribute 59 [AttributeUsage(AttributeTargets.Property)] 60 public class PropertyOrderAttribute : Attribute 61 { 62 // 63 // Simple attribute to allow the order of a property to be specified 64 // 65 private int _order; 66 public PropertyOrderAttribute(int order) 67 { 68 _order = order; 69 } 70 71 public int Order 72 { 73 get 74 { 75 return _order; 76 } 77 } 78 } 79 #endregion 80 81 #region Helper Class - PropertyOrderPair 82 public class PropertyOrderPair : IComparable 83 { 84 private int _order; 85 private string _name; 86 public string Name 87 { 88 get 89 { 90 return _name; 91 } 92 } 93 94 public PropertyOrderPair(string name, int order) 95 { 96 _order = order; 97 _name = name; 98 } 99 100 public int CompareTo(object obj) 101 { 102 // 103 // Sort the pair objects by ordering by order value 104 // Equal values get the same rank 105 // 106 int otherOrder = ((PropertyOrderPair)obj)._order; 107 if (otherOrder == _order) 108 { 109 // 110 // If order not specified, sort by name 111 // 112 string otherName = ((PropertyOrderPair)obj)._name; 113 return string.Compare(_name,otherName); 114 } 115 else if (otherOrder > _order) 116 { 117 return -1; 118 } 119 return 1; 120 } 121 } 122 #endregion
6.如果想隐藏Font这样的属性的一些英文属性,仅保留中文属性的话:(因为按照上面的步骤,你会发现,像Font这样的属性会同时包含中文和因为的属性,发现英文的会有点多余)
public class HideFontSubPropConverter : FontConverter
{
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
return new PropertyDescriptorCollection(null);
}
}
/// <summary>
/// string不展开
/// </summary>
public class HideStringSubPropConverter : StringConverter
{
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
return new PropertyDescriptorCollection(null);
}
}
/// <summary>
/// size不展开
/// </summary>
public class HideSizeSubPropConverter : SizeConverter
{
public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
{
return new PropertyDescriptorCollection(null); ;
}
}