特性与设计时支持
设计时支持扩展通常是在与组件代码不在一起的代码中实现的。 许多特性都用于将设计时支持提供程序与一个类型或一个类型的单个成员关联。
关联设计时支持特性
DesignerAttribute 使设计器与类型关联。 TypeConverterAttribute 使类型转换器与类型或类型成员关联。 EditorAttribute 使 UI 类型编辑器与类型或类型成员关联。
自定义组件初始化特性
通过将 DefaultValueAttribute 应用于属性,在设计时加载组件时,可以为要设置的属性指定默认值。 DefaultValueAttribute 在设计时重写由组件初始化代码设置的值,但该特性不重写由设计器设置的值。
自定义属性窗口行为的特性
通过向属性或事件应用 BrowsableAttribute,可以指示是否应在**“属性”窗口中列出该属性或事件。 您还可以在设计时使用实现 IDesignerFilter 接口的设计器来修改对“属性”窗口公开的属性和事件的集合。 通过对属性或事件应用 CategoryAttribute,可以指定属性或事件在“属性”窗口中应列在哪个类别下。 通过对属性或事件应用 DescriptionAttribute,可以指定要在“属性”**窗口中显示的对属性或事件的说明。
通过将 DesignOnlyAttribute 应用于属性,可以指定是否只能在设计时设置属性。 通过将 ReadOnlyAttribute 应用于属性,可以指定在设计时属性是只读还是可读/写。
通过向属性应用 ParenthesizePropertyNameAttribute 的 true 值,您可以指定在**“属性”**窗口中列出该属性时其名称是否应括在括号中。
通过将 NotifyParentPropertyAttribute 应用于应该引发通知的嵌套属性,可以指定当嵌套属性的值改变时,是否应该通知具有嵌套属性或子级属性的属性。
通过对属性或事件应用 RefreshPropertiesAttribute 和相应的 RefreshProperties 值,您可以指定:是应该刷新组件的属性、不应刷新属性,还是应该重新绘制设计器视图。
自定义设计时序列化行为特性
通过对属性应用 DesignerSerializationVisibilityAttribute 和相应的 DesignerSerializationVisibility 枚举值,您可以指定:是要序列化属性的值,还是要序列化集合属性的值。 Visual Studio 中对此任务提供了广泛的支持。 有关更多信息,请参见 演练:使用 DesignerSerializationVisibilityAttribute 序列化标准类型的集合 和 演练:使用 DesignerSerializationVisibilityAttribute 序列化标准类型的集合 和 演练:使用 DesignerSerializationVisibilityAttribute 序列化标准类型的集合 和 演练:使用 DesignerSerializationVisibilityAttribute 序列化标准类型的集合.
通过将 SerializableAttribute 应用于类型,可以将类型指定为可序列化类型。 通过实现 ISerializable 接口或提供自定义序列化程序,可以提供自定义序列化。 有关序列化的更多信息,请参见 Serialization。
有关常用设计时特性的更多信息,请参见 组件的设计时特性)。
应用特性
设计时特性应用于属性、事件和类,甚至应用于程序集。 下面的代码示例说明了应用于类,然后应用于属性和事件的特性。
' The attribute is the element in angle brackets, and the parameters
' in the attribute syntax are arguments of the constructor
' of the attribute class.
'
' Attributes applied at the class level.
<DefaultEvent("ValueChanged"), _
DefaultProperty("Number")> _
Public Class MyControl
Inherits Control
...
' Attribute applied to a property.
<DefaultValue(False)> _
Public Shadows ReadOnly Property TabStop() As Boolean
...
End Property
' Attribute applied to a property.
<CategoryAttribute("Data")> _
Public ReadOnly Property Number() As Integer
...
End Property
' Attribute applied to an event.
<Description("Raised when the Value displayed changes.")> _
Public Event ValueChanged As EventHandler
...
End Class
// The attribute is the element in brackets, and the parameters in
// the attribute syntax are arguments of the constructor
// of the attribute class.
//
// Attributes applied at the class level.
[DefaultEvent("ValueChanged")]
[DefaultProperty("Number")]
public class MyControl : Control {
...
// Attribute applied to a property.
[DefaultValue(false)]
public new bool TabStop {...
}
// Attribute applied to a property.
[CategoryAttribute("Data")]
public int Number {...}
// Attribute applied to an event.
[Description("Raised when the Value displayed changes.")]
public event EventHandler ValueChanged;
}
根据约定,特性类称为“特性名称 特性”。 System.ComponentModel 命名空间包含许多基特性类。
设计时特性与继承
从具有设计时特性的基组件派生组件或控件时,组件继承基类的设计时功能。 如果基本功能足以满足需要,则不必再次应用特性。 但是,可以重写相同类型的特性或将其他特性应用于派生的组件。 下面的代码片段演示一个自定义控件,该控件通过重写基类中应用的 BrowsableAttribute 特性,重写从 Control 继承的 Text 属性。
Public Class MyControl
Inherits Control
' The base class has [Browsable(true)] applied to the Text property.
<Browsable(False)> _
Public Overrides Property [Text]() As String
...
End Property
...
End Class
public class MyControl : Control {
// The base class has [Browsable(true)] applied to the Text property.
[Browsable(false)]
public override string Text {...}
...
}
应用类型转换器、UI 类型编辑器或设计器特性
要使设计时支持提供程序与类型或类型成员关联,请应用类声明或成员声明上面一行上的相应的特性类型。 下面的代码示例演示应用于类型的 TypeConverterAttribute。
<TypeConverter(GetType(MyColorConverter)), _
Editor(GetType(MyColorEditor), GetType(UITypeEditor))> _
Structure MyColor
...
End Structure
[ TypeConverter(typeof(MyColorConverter))]
[ Editor(typeof(MyColorEditor), typeof(UITypeEditor))]
struct MyColor {...}
如果属性类型不具有与之关联的类型转换器或 UI 类型编辑器,或者您想要重写与属性类型关联的默认类型转换器或 UI 类型编辑器,可以将特性应用于属性自身。 若要将类型转换器与属性关联,请将 TypeConverterAttribute 应用于属性声明,如下面的代码示例所示。
<TypeConverter(GetType(PointConverter))> _
Public Property MyLocation() As Point
...
End Property
[ TypeConverter(typeof(PointConverter))]
public Point MyLocation {...}
若要使 UI 类型编辑器与属性关联,请将 EditorAttribute 应用于该属性,如下面的代码示例所示。
<Editor(GetType(FlashTrackBarDarkenByEditor), _
GetType(UITypeEditor))> _
Public Property DarkenBy() As Byte
...
End Property
[ Editor(typeof(FlashTrackBarDarkenByEditor), typeof(UITypeEditor))]
public byte DarkenBy {...}
设计器可以与类型关联,但不能与属性关联。 若要使设计器与类型关联,请在类声明上面一行应用 DesignerAttribute,如下面的代码示例所示。
<Designer(GetType(HelpLabel.HelpLabelDesigner))> _
Public Class HelpLabel
Inherits System.Windows.Forms.Control
Implements System.ComponentModel.IExtenderProvider
...
End Class
[Designer(typeof(HelpLabel.HelpLabelDesigner))]
public class HelpLabel : System.Windows.Forms.Control, System.ComponentModel.IExtenderProvider {...}
提示
在上面的示例中,TypeConverterAttribute、EditorAttribute 和 DesignerAttribute 类的构造函数将 System.Type 对象作为它们的参数接受。 如果类型与设计时类位于同一程序集中,这些特性的这种形式的构造函数将有效。 如果设计时类位于其他程序集中,则需要另一种形式的特性构造函数(称为程序集限定格式),如下面的代码示例所示。
<Designer("System.Windows.Forms.Design.DocumentDesigner, System.Design")> _
Public Class MyForm
Inherits Form
...
End Class
[Designer("System.Windows.Forms.Design.DocumentDesigner, System.Design")]
public class MyForm : Form {...}
程序集级别设计时特性
ASP.NET 提供了一个程序集级别特性 (System.Web.UI.TagPrefixAttribute),该特性使控件开发人员能够为 ASP.NET 控件指定标记前缀。 在 Register 指令中,该标记前缀由 Visual Studio 为控件自动插入,所以控件可以在页中以声明方式同预先指定的标记前缀 (<标记前缀:控件名称runat = server /> ) 一同使用。
提示
TagPrefixAttribute 仅在可视化设计器中有效。 如果使用“记事本”这样的文本编辑器创作 ASP.NET 页,则需要在 Register 指令中亲自为控件指定标记前缀和命名空间。
下面的代码示例演示如何应用 TagPrefixAttribute。 特性构造函数的第一个参数指定命名空间,第二个参数指定标记前缀。
<assembly: TagPrefix("SimpleControls", "simple")>
Namespace SimpleControls
<Designer("SimpleControl.Design.SimpleDesigner, SimpleControl")> _
Public Class SimpleControl
Inherits System.Web.UI.WebControls.WebControl
...
End Class
End Namespace
[ assembly:TagPrefix("SimpleControls", "simple") ]
namespace SimpleControls {
[
Designer("SimpleControl.Design.SimpleDesigner, SimpleControl")
]
public class SimpleControl : System.Web.UI.WebControls.WebControl {}
}