首页 > 代码库 > PropertyGrid—添加EventTab
PropertyGrid—添加EventTab
零.引言
前面一篇文章介绍了如何在PropertyGrid中添加属性Tab,本文主要介绍如何添加事件选项卡。事件在许多对象中都有,尤其是在控件中,如何让对象的事件在PropertyGrid中显示出来呢,本文将进行简单的说明。
一.回顾添加属性Tab
在上篇文章中详细的讲解了如何添加属性Tab,这里简单回顾一下:
1.新建一个Tab类并继承于PropertyTab。
2.重写TabName和Bitmap属性以及GetProperties方法。
3.给特定类添加PropertyTab特性或将自定义Tab类添加到PropertyGrid的PropertyTabs集合中。
三步就可以完成了,添加EventTab与此类似,现在问题的关键在于我们要显示的是事件,而GetProperties方法只能返回属性集合(PropertyDescriptorCollection)。怎么办呢,很简单,我们把事件封装成PropertyDescriptor,再返回就行了。
二. 添加EventTab
GetProperties方法只能返回属性集合。那我们就把事件封装成PropertyDescriptor。首先定义一个封装事件的类,该类继承于PropertyDescriptor:
1 class EventWrapper : PropertyDescriptor 2 { 3 string name; //名字 4 public EventWrapper(string name) 5 : base(name, null) 6 { 7 this.name = name; 8 } 9 10 public override bool CanResetValue(object component)11 {12 return true;13 }14 15 public override string DisplayName16 {17 get18 {19 return name;20 }21 }22 23 public override string Description24 {25 get26 {27 return string.Format("{0} description", name);28 }29 }30 31 public override bool IsReadOnly32 {33 get { return false; }34 }35 36 public override string Name37 {38 get39 {40 return "fs2_" + name;41 }42 }43 44 public override Type ComponentType45 {46 get { throw new NotImplementedException(); }47 }48 49 public override object GetValue(object component)50 {51 //do something52 return "";53 }54 55 public override Type PropertyType56 {57 get { return typeof(string); }58 }59 60 public override void ResetValue(object component)61 {62 throw new NotImplementedException();63 }64 65 public override void SetValue(object component, object value)66 {67 //do something68 }69 70 public override bool ShouldSerializeValue(object component)71 {72 return false;73 }74 }
继承PropertyDescriptor时,需要重写一些属性和方法。封装类中,我们定义了一个name,用来保存事件的名称。好了,现在EventWrapper是从PropertyDescriptor继承而来,可以作为GetProperties方法的返回类型了。
接下来像前一篇文章一样定义一个EventsTab选型卡类:
1 public class EventsTab : System.Windows.Forms.Design.PropertyTab 2 { 3 [BrowsableAttribute(true)] 4 // This string contains a Base-64 encoded and serialized example property tab image. 5 private string img = "AAEAAAD/////AQAAAAAAAAAMAgAAAFRTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0xLjAuMzMwMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAA9gAAAAJCTfYAAAAAAAAANgAAACgAAAAIAAAACAAAAAEAGAAAAAAAAAAAAMQOAADEDgAAAAAAAAAAAAD///////////////////////////////////9ZgABZgADzPz/zPz/zPz9AgP//////////gAD/gAD/AAD/AAD/AACKyub///////+AAACAAAAAAP8AAP8AAP9AgP////////9ZgABZgABz13hz13hz13hAgP//////////gAD/gACA/wCA/wCA/wAA//////////+AAACAAAAAAP8AAP8AAP9AgP////////////////////////////////////8L"; 6 7 public override System.ComponentModel.PropertyDescriptorCollection GetProperties(object component, Attribute[] attributes) 8 { 9 //Return list of known events10 EventDescriptorCollection events_info;11 if (attributes == null)12 events_info = TypeDescriptor.GetEvents(component);13 else14 events_info = TypeDescriptor.GetEvents(component, attributes);15 //封装事件16 var events = new PropertyDescriptor[events_info.Count];17 for (int i = 0; i < events_info.Count; i++)18 events[i] = new EventWrapper(events_info[i].Name);19 20 return new PropertyDescriptorCollection(events);21 }22 23 public override string TabName24 {25 get { return "Events"; }26 }27 28 public override System.Drawing.Bitmap Bitmap29 {30 get31 {32 Bitmap bmp = new Bitmap(DeserializeFromBase64Text(img));33 34 return bmp;35 }36 }37 38 private Image DeserializeFromBase64Text(string text)39 {40 Image img = null;41 byte[] memBytes = Convert.FromBase64String(text);42 IFormatter formatter = new BinaryFormatter();43 MemoryStream stream = new MemoryStream(memBytes);44 img = (Image)formatter.Deserialize(stream);45 stream.Close();46 return img;47 }48 }
唯一的不同是在Getproperties方法中,我们先获取对象的事件信息,再将其封装为我们定义的事件封装类,并返回。
现在要做的就是将我们定义的EventsTab类型添加到PropertyGrid控件的PropertyTabs集合中,将MyControl对象赋值给PropertyGrid控件的SelectedObject属性,运行程序,就可以看到MyControl对象的事件列表,效果如下:
可见,事件都列出来了。
三.完整代码
下面是完整代码:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Windows.Forms; 6 using System.Windows.Forms.Design; 7 using System.ComponentModel; 8 using System.ComponentModel.Design; 9 using System.Drawing; 10 using System.IO; 11 using System.Runtime.Serialization; 12 using System.Runtime.Serialization.Formatters.Binary; 13 14 namespace TestAddTab 15 { 16 //控件类 17 //[PropertyTabAttribute(typeof(MyPropertyTab), PropertyTabScope.Component)] 18 public class MyControl : System.Windows.Forms.UserControl 19 { 20 private double _angle = 90; 21 22 public MyControl() 23 { 24 } 25 26 [BrowsableAttribute(true)] 27 [Category("角度")] 28 public double Angle 29 { 30 get 31 { return _angle; } 32 set 33 { _angle = value; } 34 } 35 36 37 protected override void OnPaint(System.Windows.Forms.PaintEventArgs e) 38 { 39 e.Graphics.DrawString("The Angle is " + _angle, this.Font, Brushes.Red, 0, 0); 40 } 41 } 42 43 public class EventsTab : System.Windows.Forms.Design.PropertyTab 44 { 45 [BrowsableAttribute(true)] 46 // This string contains a Base-64 encoded and serialized example property tab image. 47 private string img = "AAEAAAD/////AQAAAAAAAAAMAgAAAFRTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0xLjAuMzMwMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAA9gAAAAJCTfYAAAAAAAAANgAAACgAAAAIAAAACAAAAAEAGAAAAAAAAAAAAMQOAADEDgAAAAAAAAAAAAD///////////////////////////////////9ZgABZgADzPz/zPz/zPz9AgP//////////gAD/gAD/AAD/AAD/AACKyub///////+AAACAAAAAAP8AAP8AAP9AgP////////9ZgABZgABz13hz13hz13hAgP//////////gAD/gACA/wCA/wCA/wAA//////////+AAACAAAAAAP8AAP8AAP9AgP////////////////////////////////////8L"; 48 49 50 public override System.ComponentModel.PropertyDescriptorCollection GetProperties(object component, Attribute[] attributes) 51 { 52 //Return list of known events 53 EventDescriptorCollection events_info; 54 if (attributes == null) 55 events_info = TypeDescriptor.GetEvents(component); 56 else 57 events_info = TypeDescriptor.GetEvents(component, attributes); 58 59 var events = new PropertyDescriptor[events_info.Count]; 60 for (int i = 0; i < events_info.Count; i++) 61 events[i] = new EventWrapper(events_info[i].Name); 62 63 return new PropertyDescriptorCollection(events); 64 } 65 66 public override string TabName 67 { 68 get { return "Events"; } 69 } 70 71 public override System.Drawing.Bitmap Bitmap 72 { 73 get 74 { 75 Bitmap bmp = new Bitmap(DeserializeFromBase64Text(img)); 76 return bmp; 77 } 78 } 79 80 private Image DeserializeFromBase64Text(string text) 81 { 82 Image img = null; 83 byte[] memBytes = Convert.FromBase64String(text); 84 IFormatter formatter = new BinaryFormatter(); 85 MemoryStream stream = new MemoryStream(memBytes); 86 img = (Image)formatter.Deserialize(stream); 87 stream.Close(); 88 return img; 89 } 90 } 91 92 class EventWrapper : PropertyDescriptor 93 { 94 string name; 95 public EventWrapper(string name) 96 : base(name, null) 97 { 98 this.name = name; 99 }100 101 public override bool CanResetValue(object component)102 {103 return true;104 }105 106 public override string DisplayName107 {108 get109 {110 return name;111 }112 }113 114 public override string Description115 {116 get117 {118 return string.Format("{0} description", name);119 }120 }121 122 public override bool IsReadOnly123 {124 get { return false; }125 }126 127 public override string Name128 {129 get130 {131 return "fs2_" + name;132 }133 }134 135 public override Type ComponentType136 {137 get { throw new NotImplementedException(); }138 }139 140 public override object GetValue(object component)141 {142 //do something143 return "";144 }145 146 public override Type PropertyType147 {148 get { return typeof(string); }149 }150 151 public override void ResetValue(object component)152 {153 throw new NotImplementedException();154 }155 156 public override void SetValue(object component, object value)157 {158 //do something159 }160 161 public override bool ShouldSerializeValue(object component)162 {163 return false;164 }165 }166 }
新建Windows工程,添加该文件,在Form中拖入一个PropertyGrid控件和MyControl控件,在Form的构造函数中添加如下代码:
this.propertyGrid1.PropertyTabs.AddTabType(typeof(EventsTab));
this.propertyGrid1.SelectedObject = this.myControl1;
运行程序,查看效果。
这里只是实现了非常简单的功能,仅仅显示了控件的事件,而不能编辑,如果要达到VS那种效果,需要完善EventWrapper类。
还是那句话,个人浅见,错漏不正之处,敬请指出,万分感谢!
PropertyGrid—添加EventTab