编写组件自己的设计器

摘要:
当通过PropertyDescriptor更改属性的值时,组件通知信息将自动发送,这是一种相对简单的通知工作方式。为组件定制的设计器可以具有不同于标准界面的设计界面,并且可以将设计时代码与执行时代码分开,减少已发布文件的大小,并更有力地控制组件的设计时行为。通过使用这些功能来扩展组件,我们可以拥有更丰富的设计时行为和运行时对象模型。

http://ms.mblogger.cn/soil/posts/5046.aspx

当设计器改变了一个组件的状态时,其他的一些组件可能会对这个改变有兴趣。举一个例子,如果你改变了一个组件的背景为红色,属性窗口会显示这个改变信息。一般的,组件状态的改变会通过IComponentChangeService广播出去。VS.NET设计器中的其他服务会监听这个IComponentChangeService,包括代码持久性引擎,redo/undo工具,属性窗口和对这个更新有兴趣的属性的更新状态。

IComponentService在一个组件将要改变和改变后都会得到注意。任何客户都会收到两个主要的通知信息:OnComponentChanging和OnComponentChanged。OnComponentChanging必须在OnComponentChanged之前触发,而OnComponentChanged并不需要在IComponentChanging之后调用。当由于某种原因取消动作时这个就可以起作用。IComponentChangeService有好几个监听通知的事件。
lComponentChanging
lComponentChanged
lComponentAdding
lComponentAdded
lComponentRemoving
lComponentRemoved
lComponentRename
服务仅仅允许ComponentChanging和ComponentChanged手动触发。其他的事件都是设计器在组件添加、删除、更改名字的时候自动触发的。
当通过PropertyDescriptor改变一个属性的值时,组件通知信息自动就发送出去,也就是这是一个相当简便的方式来做一些通知工作。
在上面的例子里,如果我们用PropertyDescriptor来通知改变(属性窗口会自动更新),我们把动作处理的代码改成如下:

private void OnVerbGreen(object sender, EventArgs e){
PropertyDescriptor backColorProp =
TypeDescriptor.GetProperties(Control)["BackColor"];

if (backColorProp != null) {
backColorProp.SetValue(Control, Color.Green);
}
}

同样有一些情况是改变一个属性的值会影响到其他的一些属性,或者是一些情况是许多属性的改变同时发生。考虑到性能因素,直接修改对象的属性值(而不是使用PropertyDescriptor),然后接着调用通知。用PropertyDescriptor来访问属性会比直接来得慢。
我们看一下RadioButton。当改变一个RadioButton的值为true时,其他的有同一个parent对象的RadioButton就应该设置为false。运行期代码会自动处理这些,不过设计时期还是要自己来处理比较好。在这个例子里,我们把Checked属性影化来中途截取改变的值。当值设为true时,我们就循环处理RadioButton的兄弟,并且通知每一个RadioButton的IComponentService来改变他们的值。我们通过调用ComponentDesigner的GetService方法来得到一个IComponentService对象句柄然后调用他的实例。

internal class RadioButtonDesigner : ControlDesigner {

public bool Checked {
get {
// pass the get down to the control.
//
return ((RadioButton)Control).Checked;
}
set {
// set the value into the control
//
((RadioButton)Control).Checked = value;

// if the value for this radio button
// was set to true, notify that others have changed.
//
if (value) {
IComponentChangeService ccs =
(IComponentChangeService)
GetService(typeof(IComponentChangeService));
if (ccs != null) {
PropertyDesciptor checkedProp =
TypeDescriptor.GetProperties(typeof(RadioButton))["Checked"];
foreach(RadioButton rb in
Control.Parent.Controls) {
if (rb == Control || !(rb is RadioButton))
continue;

ccs.OnComponentChanging(rb, checkedProp);
ccs.OnComponentChanged(rb,chedkedProp, null, null);
}
}
}
}
}

protected override void PreFilterProperties(
IDictionary properties) {
base.PreFilterProperties(properties);
// shadow the checked property so we can intercept the set.
//
properties["Checked"] =
TypeDescriptor.CreateProperty( typeof(RadioButtonDesigner),
(PropertyDescriptor)properties["Checked"],
new Attribute[0]);
}
}

 
 
结论
设计器可以给任何实现IComponent的对象编写并且驻扎(sited)在设计界面上。这对Windows Forms Controls、Web Form Controls和其他的组件来说都是适用的。给组件订制的设计器可以有不同于标准的设计界面而且可以让设计时期代码和执行时期代码分离,减少发布文件大小而且可以更强的控制组件的设计期行为。
从扩展性能上说,从.NET框架的设计时期接口和类导出的对象有能力订制自己的设计期行为,而以前的框架没有这些。运用这些能力来扩展组件就可以有更加丰富的设计期行为和运行期对象模型。

免责声明:文章转载自《编写组件自己的设计器》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇终端不识别手机设备解决方案svn如何过滤常见的bin/obj/package/log等文件夹的文件下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

随便看看

Jumpserver-堡垒机

管理用户是资产的根用户,或具有NOPASSWD:ALLsudo权限的用户。Jumpserver使用此用户推送系统用户并获取资产硬件信息。使用Web终端连接到服务器后,我查看当前用户,显示为Jumpserver。下面是一个通过单击Docker直接安装koko的命令。当系统用户创建时,如果选择了自动推送,Jumpserver将使用...

boost的下载和安装(windows版)

1 Introduction boost是一个准C++标准库,相当于STL的延续和扩展。它的设计理念类似于STL,它使用泛型来最大化重用。对于2boost的下载和安装,我们可以在官方boost网站上下载最新的boost版本。因为boost库可以像标准库一样在多个平台上运行,所以它只以源代码的形式正式提供。这是因为boost windows的安装版本不仅与处理...

Java switch 枚举

Switch可以使用int.short、char、Enum和String其中,Enum是1.5之后的新特性,String是java8的新特性。所以正确的写作应该如下。...

传奇服务端各文件用途说明

传奇外传服务端├数据库服务器│├联系│├美国联邦储备银行│├日志│├! ID列表。txt(付款帐户列表,在Setup.exe中ServiceMode=TRUE时有效)!服务器信息.txt│├DBServer.exe│└DBSrc.ini├登录门│├登录网关.exe│└配置ini├登录服务器│├Chr日志│├ConLog公司│├计数日志│├国际数据库││├ID...

win server2008关闭危险端口445,135,137,138,139的方法

在Windowsserver2008系统上,有两种途经可以禁用本地端口:1、通过Windows防火墙2、通过IP安全策略一、通过Windows防火墙禁用端口:1、点击“控制面板-Windows防火墙”,确保启用了Windows防火墙。重复操作,添加135、137、138、139规则然后在新规则属性中,单击筛选器操作选项卡单击下方的添加,并且不要勾选右侧的使用...

ORACLE无法删除当前连接用户

今天在做Oracle数据库是遇到ORACLE无法删除当前连接用户,经查找可用如下方法解决。SQL˃dropuseracascade;//删除用户以及用户表空间下所有对象用户已丢弃。...