在
上一篇文章中,曾经提及“复杂属性”的概念。复杂属性的最大特征是属性的类型是本身具有属性(称为子属性)的类。通常情况下,复杂属性表现为3种形式:连字符形式属性、内部嵌套形式属性和内部嵌套形式默认属性。本文将介绍以上3种形式复杂属性的具体实现方法。
1. 实现连字符形式复杂属性 连字符形式属性是比较常见的复杂属性。我们常用的Font属性就是一个复杂属性,其包括多个子属性,如Bold、Name等。这种类型属性具有两种语法格式:一种是利用连字符语法,在控件的开始标记中保存子属性,例如,Font-Bold,Font-Name。另外一种格式是在控件的标记中保存子属性,例如,<font Bold="true" />。后者比前者的可读性强。
实现连字符形式的复杂属性,必须对该复杂属性及其子属性实现设置指定的设计时元数据。下面首先列举了复杂属性实现过程中的相关元数据设置示例。请阅读下面的源代码。
public class CustomerControl:WebControl{ [ DesignerSerializationVisibility( DesignerSerializationVisibility.Content), NotifyParentProperty(true) ] public SizeInfo Size { ...... } } |
如上代码所示,Size是一个复杂属性,其属性类型为SizeInfo(自定义类)。在Size属性实现前设置了两个设计时元数据:DesignerSerializationVisibility和NotifyParentProperty。DesignerSerializationVisibility用于指定在设计时序列化组件上的属性时,所使用的持久性类型。其值设置为DesignerSerializationVisibility.Content枚举值,用于指定序列化程序应该序列化属性的内容即子属性,而不是Size属性本身,因为序列化Size没有任何意义。另外,还包括一个NotifyParentProperty(true)设置,它的作用是使得属性浏览器中对子属性的修改通知一直上传到对象模型,并在被修改了子属性的控件中产生修改通知。
在完成了复杂属性的元数据设置后,开发人员还必须对子属性设置相关的设计时元数据。例如,Size包括两个子属性Height和Width,那么它们的实现代码应如下所示。
[TypeConverter(typeof(ExpandableObjectConverter))]public class SizeInfo{ [ NotifyParentProperty(true) ] public UInt32 Height {......} [ NotifyParentProperty(true) ] public UInt32 Width {......} } |
如上代码所示,子属性Height和Width分别被设置了元数据NotifyParentProperty(true)。这样,当子属性发生修改时,.NET框架将自动产生修改通知,并且通知到父属性Size。另外,还有一个设计时特性TypeConverter(typeof(ExpandableObjectConverter)),它告诉属性浏览器提供扩展和折叠样式,这样控件开发者可以在属性浏览器中直接编辑子属性。
以上介绍了声明连字符形式属性的方法。从中可以看出,在声明连字符属性过程中需要把握两个要点:一是复杂属性的设计时元数据设置;二是子属性的设计时特性设置。