景林

爬上巨人的肩膀

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

零.引言

  前面一篇文章介绍了如何在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对象的事件列表,效果如下:

  

  可见,事件都列出来了。

三.完整代码

  下面是完整代码:

  
  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类。

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

posted on 2015-01-18 22:28  景林  阅读(846)  评论(0编辑  收藏  举报