首页 > 代码库 > 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     }
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 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 }
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 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 }
View Code

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

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

  this.propertyGrid1.SelectedObject = this.myControl1;

  运行程序,查看效果。

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

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

PropertyGrid—添加EventTab