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:
class EventWrapper : PropertyDescriptor
{
string name; //名字
public EventWrapper(string name)
: base(name, null)
{
this.name = name;
} public override bool CanResetValue(object component)
{
return true;
} public override string DisplayName
{
get
{
return name;
}
} public override string Description
{
get
{
return string.Format("{0} description", name);
}
} public override bool IsReadOnly
{
get { return false; }
} public override string Name
{
get
{
return "fs2_" + name;
}
} public override Type ComponentType
{
get { throw new NotImplementedException(); }
} public override object GetValue(object component)
{
//do something
return "";
} public override Type PropertyType
{
get { return typeof(string); }
} public override void ResetValue(object component)
{
throw new NotImplementedException();
} public override void SetValue(object component, object value)
{
//do something
} public override bool ShouldSerializeValue(object component)
{
return false;
}
}
继承PropertyDescriptor时,需要重写一些属性和方法。封装类中,我们定义了一个name,用来保存事件的名称。好了,现在EventWrapper是从PropertyDescriptor继承而来,可以作为GetProperties方法的返回类型了。
接下来像前一篇文章一样定义一个EventsTab选型卡类:
public class EventsTab : System.Windows.Forms.Design.PropertyTab
{
[BrowsableAttribute(true)]
// This string contains a Base-64 encoded and serialized example property tab image.
private string img = "AAEAAAD/////AQAAAAAAAAAMAgAAAFRTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0xLjAuMzMwMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAA9gAAAAJCTfYAAAAAAAAANgAAACgAAAAIAAAACAAAAAEAGAAAAAAAAAAAAMQOAADEDgAAAAAAAAAAAAD///////////////////////////////////9ZgABZgADzPz/zPz/zPz9AgP//////////gAD/gAD/AAD/AAD/AACKyub///////+AAACAAAAAAP8AAP8AAP9AgP////////9ZgABZgABz13hz13hz13hAgP//////////gAD/gACA/wCA/wCA/wAA//////////+AAACAAAAAAP8AAP8AAP9AgP////////////////////////////////////8L"; public override System.ComponentModel.PropertyDescriptorCollection GetProperties(object component, Attribute[] attributes)
{
//Return list of known events
EventDescriptorCollection events_info;
if (attributes == null)
events_info = TypeDescriptor.GetEvents(component);
else
events_info = TypeDescriptor.GetEvents(component, attributes);
//封装事件
var events = new PropertyDescriptor[events_info.Count];
for (int i = ; i < events_info.Count; i++)
events[i] = new EventWrapper(events_info[i].Name); return new PropertyDescriptorCollection(events);
} public override string TabName
{
get { return "Events"; }
} public override System.Drawing.Bitmap Bitmap
{
get
{
Bitmap bmp = new Bitmap(DeserializeFromBase64Text(img)); return bmp;
}
} private Image DeserializeFromBase64Text(string text)
{
Image img = null;
byte[] memBytes = Convert.FromBase64String(text);
IFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream(memBytes);
img = (Image)formatter.Deserialize(stream);
stream.Close();
return img;
}
}
唯一的不同是在Getproperties方法中,我们先获取对象的事件信息,再将其封装为我们定义的事件封装类,并返回。
现在要做的就是将我们定义的EventsTab类型添加到PropertyGrid控件的PropertyTabs集合中,将MyControl对象赋值给PropertyGrid控件的SelectedObject属性,运行程序,就可以看到MyControl对象的事件列表,效果如下:

可见,事件都列出来了。
三.完整代码
下面是完整代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Windows.Forms.Design;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary; namespace TestAddTab
{
//控件类
//[PropertyTabAttribute(typeof(MyPropertyTab), PropertyTabScope.Component)]
public class MyControl : System.Windows.Forms.UserControl
{
private double _angle = ; public MyControl()
{
} [BrowsableAttribute(true)]
[Category("角度")]
public double Angle
{
get
{ return _angle; }
set
{ _angle = value; }
} protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
e.Graphics.DrawString("The Angle is " + _angle, this.Font, Brushes.Red, , );
}
} public class EventsTab : System.Windows.Forms.Design.PropertyTab
{
[BrowsableAttribute(true)]
// This string contains a Base-64 encoded and serialized example property tab image.
private string img = "AAEAAAD/////AQAAAAAAAAAMAgAAAFRTeXN0ZW0uRHJhd2luZywgVmVyc2lvbj0xLjAuMzMwMC4wLCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWIwM2Y1ZjdmMTFkNTBhM2EFAQAAABVTeXN0ZW0uRHJhd2luZy5CaXRtYXABAAAABERhdGEHAgIAAAAJAwAAAA8DAAAA9gAAAAJCTfYAAAAAAAAANgAAACgAAAAIAAAACAAAAAEAGAAAAAAAAAAAAMQOAADEDgAAAAAAAAAAAAD///////////////////////////////////9ZgABZgADzPz/zPz/zPz9AgP//////////gAD/gAD/AAD/AAD/AACKyub///////+AAACAAAAAAP8AAP8AAP9AgP////////9ZgABZgABz13hz13hz13hAgP//////////gAD/gACA/wCA/wCA/wAA//////////+AAACAAAAAAP8AAP8AAP9AgP////////////////////////////////////8L"; public override System.ComponentModel.PropertyDescriptorCollection GetProperties(object component, Attribute[] attributes)
{
//Return list of known events
EventDescriptorCollection events_info;
if (attributes == null)
events_info = TypeDescriptor.GetEvents(component);
else
events_info = TypeDescriptor.GetEvents(component, attributes); var events = new PropertyDescriptor[events_info.Count];
for (int i = ; i < events_info.Count; i++)
events[i] = new EventWrapper(events_info[i].Name); return new PropertyDescriptorCollection(events);
} public override string TabName
{
get { return "Events"; }
} public override System.Drawing.Bitmap Bitmap
{
get
{
Bitmap bmp = new Bitmap(DeserializeFromBase64Text(img));
return bmp;
}
} private Image DeserializeFromBase64Text(string text)
{
Image img = null;
byte[] memBytes = Convert.FromBase64String(text);
IFormatter formatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream(memBytes);
img = (Image)formatter.Deserialize(stream);
stream.Close();
return img;
}
} class EventWrapper : PropertyDescriptor
{
string name;
public EventWrapper(string name)
: base(name, null)
{
this.name = name;
} public override bool CanResetValue(object component)
{
return true;
} public override string DisplayName
{
get
{
return name;
}
} public override string Description
{
get
{
return string.Format("{0} description", name);
}
} public override bool IsReadOnly
{
get { return false; }
} public override string Name
{
get
{
return "fs2_" + name;
}
} public override Type ComponentType
{
get { throw new NotImplementedException(); }
} public override object GetValue(object component)
{
//do something
return "";
} public override Type PropertyType
{
get { return typeof(string); }
} public override void ResetValue(object component)
{
throw new NotImplementedException();
} public override void SetValue(object component, object value)
{
//do something
} public override bool ShouldSerializeValue(object component)
{
return false;
}
}
}
新建Windows工程,添加该文件,在Form中拖入一个PropertyGrid控件和MyControl控件,在Form的构造函数中添加如下代码:
this.propertyGrid1.PropertyTabs.AddTabType(typeof(EventsTab));
this.propertyGrid1.SelectedObject = this.myControl1;
运行程序,查看效果。
这里只是实现了非常简单的功能,仅仅显示了控件的事件,而不能编辑,如果要达到VS那种效果,需要完善EventWrapper类。
还是那句话,个人浅见,错漏不正之处,敬请指出,万分感谢!
PropertyGrid—添加EventTab的更多相关文章
- PropertyGrid—添加属性Tab
零.引言 PropertyGrid用来显示和编辑对象的属性,前面已经简单介绍了如何使用该控件和提供不同的属性编辑方法.前面主要讲如何使用该控件,但有时,该控件无法满足我们的需求,就需要对其进行扩展.本 ...
- PropertyGrid 重难点总结 转
PropertyGrid的界面组成与不同部分的名称如下图所示. 本博文不算是自己写作的,只是将PropertyGrid中的几项十分有用的功能的应用方面的文字进行一下总结,希望以后大家对Property ...
- PropertyGrid 重难点总结
PropertyGrid的界面组成与不同部分的名称如下图所示. 本博文不算是自己写作的,只是将PropertyGrid中的几项十分有用的功能的应用方面的文字进行一下总结,希望以后大家对Property ...
- 关于PropertyGrid控件的排序问题
前些天,由于在项目中需要用到PropertyGrid这个控件,展现其所在控件的某些属性,由于有些控件的属性较多,不易浏览,而且PropertyGrid的排序默认的按照字母的顺序排列的,这样导致在在某些 ...
- C# extended toolkit propertygrid 隐藏部分属性
该方法是通过更改ShowDetail的状态来实现的隐藏属性 首先在引用里右键 管理NuGet程序包 查找extended wpf toolkit 并安装 然后在MainWindow.xaml添加引用 ...
- C#动态添加属性
class DynamicInputParams: DynamicObject { Dictionary<string, object> property = new Dictionary ...
- WinForm窗体PropertyGrid控件的使用
使用过 Microsoft Visual Basic 或 Microsoft Visual Studio .NET的朋友,一定使用过属性浏览器来浏览.查看或编辑一个或多个对象的属性..NET 框架 P ...
- C# PropertyGrid控件应用心得
何处使用 PropertyGrid 控件 在应用程序中的很多地方,您都可以使用户与 PropertyGrid 进行交互,从而获得更丰富的编辑体验.例如,某个应用程序包含多个用户可以设置的“设置”或选项 ...
- 自定义控件如何给特殊类型的属性添加默认值 z
定义控件如何给特殊类型的属性添加默认值了,附自定义GroupBox一枚 标题有点那啥,但确实能表达我掌握此法后的心情. 写自定义控件时往往会有一个需求,就是给属性指定一个默认值(就是可以在VS中右键该 ...
随机推荐
- quick-cocos2d-x android返回键监听并实现原生退出对话框
这两天最终闲了一下,就顺手又把quick捡起来又学了学,一直都认为quick比cocos2dx那套lua绑定要方便很多,今天试了下android返回键的监听,还是挺好弄的,所以就有了这篇. 首先说明一 ...
- Android自定义带标题边框的Layout
今天工作中又碰到个小问题,项目需要用到像Java Swing的JPanel一样带标题边框的布局,Android里没有类似控件,想到这个也不难,自己画了一个,是继承LinearLayout的一个自定义布 ...
- C程序设计语言(K&R)笔记
1.表达式中float类型的操作数不会自动转换为double类型.一般来说,数学函数(如math.h)使用双精度类型的变量.使用float类型主要是为了在使用较大数组时节省存储空间,有时也为了节省机器 ...
- cacti出现snmp error
一.在被监控机器中确认snmp是否启动 service snmpd status [root@test2 ~]# service snmpd status snmpd (pid 1247) 正在运行 ...
- javascript高级知识点——memoization
memoization是一种非常有用的优化技术,它缓存特定输入产生的相应结果.这样麻烦的查找和迭代计算可以尽可能的减少. 它基本的思想是针对特定的输入,已经计算过的结果都是通过缓存当中的数据直接返回而 ...
- Java生成登陆时使用的图片验证码
package com.ws.frame.utils; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; i ...
- java学习——数组
元素类型[] 数组名 = new 元素类型[元素个数或数组长度]; array 为引用数据类型|-数组数据类型 | 内存结构:程序在运行时,需要在内存中的分配空间.为了提高运行的效率,有对空间进行不同 ...
- iOS获取文件路径
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px "PingFang SC"; color: #008400 } p.p2 ...
- [Effective Modern C++] Item 7. Distinguish between () and {} when creating objects - 辨别使用()与{}创建对象的差别
条款7 辨别使用()与{}创建对象的差别 基础知识 目前已知有如下的初始化方式: ); ; }; }; // the same as above 在以“=”初始化的过程中没有调用赋值运算,如下例所示: ...
- you can Solve a Geometry Problem too(hdoj1086)
Problem Description Many geometry(几何)problems were designed in the ACM/ICPC. And now, I also prepare ...