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 DisplayName

16         {

17             get

18             {

19                 return name;

20             }

21         }

22 

23         public override string Description

24         {

25             get

26             {

27                 return string.Format("{0} description", name);

28             }

29         }

30 

31         public override bool IsReadOnly

32         {

33             get { return false; }

34         }

35 

36         public override string Name

37         {

38             get

39             {

40                 return "fs2_" + name;

41             }

42         }

43 

44         public override Type ComponentType

45         {

46             get { throw new NotImplementedException(); }

47         }

48 

49         public override object GetValue(object component)

50         {

51             //do something

52             return "";

53         }

54 

55         public override Type PropertyType

56         {

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 something

68         }

69 

70         public override bool ShouldSerializeValue(object component)

71         {

72             return false;

73         }

74     }
View Code

  继承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 events

10             EventDescriptorCollection events_info;

11             if (attributes == null)

12                 events_info = TypeDescriptor.GetEvents(component);

13             else

14                 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 TabName

24         {

25             get { return "Events"; }

26         }

27 

28         public override System.Drawing.Bitmap Bitmap

29         {

30             get

31             {

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 }
View Code

  唯一的不同是在Getproperties方法中,我们先获取对象的事件信息,再将其封装为我们定义的事件封装类,并返回。

  现在要做的就是将我们定义的EventsTab类型添加到PropertyGrid控件的PropertyTabs集合中,将MyControl对象赋值给PropertyGrid控件的SelectedObject属性,运行程序,就可以看到MyControl对象的事件列表,效果如下:

  PropertyGrid—添加EventTab

  可见,事件都列出来了。

三.完整代码

  下面是完整代码:

  
  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 DisplayName

107         {

108             get

109             {

110                 return name;

111             }

112         }

113 

114         public override string Description

115         {

116             get

117             {

118                 return string.Format("{0} description", name);

119             }

120         }

121 

122         public override bool IsReadOnly

123         {

124             get { return false; }

125         }

126 

127         public override string Name

128         {

129             get

130             {

131                 return "fs2_" + name;

132             }

133         }

134 

135         public override Type ComponentType

136         {

137             get { throw new NotImplementedException(); }

138         }

139 

140         public override object GetValue(object component)

141         {

142             //do something

143             return "";

144         }

145 

146         public override Type PropertyType

147         {

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 something

159         }

160 

161         public override bool ShouldSerializeValue(object component)

162         {

163             return false;

164         }

165     }

166 }
View Code

  新建Windows工程,添加该文件,在Form中拖入一个PropertyGrid控件和MyControl控件,在Form的构造函数中添加如下代码:

  this.propertyGrid1.PropertyTabs.AddTabType(typeof(EventsTab));

  this.propertyGrid1.SelectedObject = this.myControl1;

  运行程序,查看效果。

  这里只是实现了非常简单的功能,仅仅显示了控件的事件,而不能编辑,如果要达到VS那种效果,需要完善EventWrapper类。

  还是那句话,个人浅见,错漏不正之处,敬请指出,万分感谢!

你可能感兴趣的:(property)