自定义控件的设计时属性(Windows 窗体 .NET)
本文介绍如何在 Visual Studio 的 Windows 窗体视觉对象设计器中为控件处理属性。
每个控件从基类 System.Windows.Forms.Control 继承许多属性,例如:
创建控件时,可以定义新属性并控制它们在设计器中的显示方式。
定义属性
具有由控件定义的 get 访问器的任何公共属性都会在 Visual Studio 属性窗口中自动显示。 如果该属性还定义了 set 访问器,则可以在“属性”窗口中更改该属性。 但是,可以通过应用 BrowsableAttribute,在”属性”窗口中显式显示或隐藏属性。 此属性采用单个布尔参数来指示是否显示它。 有关属性的详细信息,请参阅属性 (C#) 或属性概述 (Visual Basic)。
[Browsable(false)]
public bool IsSelected { get; set; }
<Browsable(False)>
Public Property IsSelected As Boolean
[注意] 无法与字符串之间隐式转换的复杂属性需要类型转换器。
序列化属性
控件上设置的属性将序列化为设计器的代码隐藏文件。 当属性的值设置为默认值以外的其他值时,将发生这种情况。
当设计器检测到对属性的更改时,它将计算控件的所有属性,并序列化其值与该属性的默认值不匹配的任何属性。 属性的值序列化为设计器的代码隐藏文件。 默认值可帮助设计器确定应序列化哪些属性值。
默认值
当属性应用 DefaultValueAttribute 特性或属性的类包含属性特定的 Reset
和 ShouldSerialize
方法时,该属性被视为具有默认值。 有关属性的详细信息,请参阅特性 (C#) 或特性概述 (Visual Basic)。
通过设置默认值,可以启用以下内容:
- 如果已将属性的值修改为非默认值,则该属性会在“属性”窗口中提供视觉指示。
- 用户可以右键单击该属性,然后选择“重置”,将属性还原为其默认值。
- 设计器生成更高效的代码。
如果属性使用简单类型(如基元类型),则可以通过将默认值应用于 DefaultValueAttribute
属性来设置。 但是,具有此特性的属性不会自动以该赋值开头。 必须将属性的支持字段设置为相同的默认值。 可以在声明或类的构造函数中设置属性。
当属性是复杂类型,或者想要控制设计器的重置和序列化行为时,请定义类的 Reset<PropertyName>
和 ShouldSerialize<PropertyName>
方法。 例如,如果控件定义 Age
属性,则方法命名为 ResetAge
和 ShouldSerializeAge
。
重要
应用 DefaultValueAttribute
到属性,或提供 Reset<PropertyName>
和 ShouldSerialize<PropertyName>
方法。 不要同时使用这两者。
可以右键单击属性名称并选择“重置”,通过“属性” 窗口将属性“重置”为默认值。
在以下情况下启用“属性”>右键单击>“重置”上下文菜单选项的可用性:
- 该属性应用了 DefaultValueAttribute 特性,并且属性的值与特性的值不匹配。
- 该属性的类定义没有
ShouldSerialize<PropertyName>
的Reset<PropertyName>
方法。 - 该属性的类定义
Reset<PropertyName>
方法,并且ShouldSerialize<PropertyName>
返回 true。
DefaultValueAttribute
如果属性的值与 DefaultValueAttribute 提供的值不匹配,则属性视为已更改,但可通过“属性”窗口重置。
重要
此特性不应该用于具有相应 Reset<PropertyName>
和 ShouldSerialize<PropertyName>
方法的属性。
以下代码声明两个属性:默认值为 North
的枚举和默认值为 10 的整数。
[DefaultValue(typeof(Directions), "North")]
public Directions PointerDirection { get; set; } = Directions.North;
[DefaultValue(10)]
public int DistanceInFeet { get; set; } = 10;
<DefaultValue(GetType(Directions), "North")>
Public Property PointerDirection As Directions = Directions.North
<DefaultValue(10)>
Public Property DistanceInFeet As Integer = 10
重置和 ShouldSerialize
如前所述,Reset<PropertyName>
和 ShouldSerialize<PropertyName>
方法不仅可用于指导属性重置行为,还可用于确定值是否已更改以及应序列化为设计器的代码隐藏文件。 这两种方法协同工作,不应定义一种而不定义另一种。
重要
不应为具有 DefaultValueAttribute 的属性创建 Reset<PropertyName>
和 ShouldSerialize<PropertyName>
方法。
定义 Reset<PropertyName>
时,“属性”窗口显示该属性的“重置”上下文菜单选项。 选择“重置”时,将调用 Reset<PropertyName>
方法。 “重置”上下文菜单选项由 ShouldSerialize<PropertyName>
方法返回的内容启用或禁用。 当 ShouldSerialize<PropertyName>
返回 true
时,它指示属性已从其默认值更改,应序列化为代码隐藏文件,并启用“重置”上下文菜单选项。 返回 false
时,将禁用“重置”上下文菜单选项,并且代码隐藏已删除属性集代码。
提示
这两种方法都可以且应该使用专用范围进行定义,以便它们不会构成控件的公共 API。
以下代码片段声明一个名为 Direction
的属性。 此属性的设计器行为由 ResetDirection
和 ShouldSerializeDirection
方法控制。
public Directions Direction { get; set; } = Directions.None;
private void ResetDirection() =>
Direction = Directions.None;
private bool ShouldSerializeDirection() =>
Direction != Directions.None;
Public Property Direction As Directions = Directions.None
Private Sub ResetDirection()
Direction = Directions.None
End Sub
Private Function ShouldSerializeDirection() As Boolean
Return Direction <> Directions.None
End Function
类型转换器
虽然类型转换器通常将一种类型转换为另一种类型,但也为属性网格和其他设计时控件提供字符串到值的转换。 字符串到值的转换允许在这些设计时控件中表示复杂属性。
大多数内置数据类型(数字、枚举和其他类型)都有提供字符串到值转换和执行验证检查的默认类型转换器。 默认类型转换器位于 System.ComponentModel
命名空间中,以转换的类型命名。 转换器类型名称使用以下格式:{type name}Converter
。 例如 StringConverter、TimeSpanConverter 和 Int32Converter。
类型转换器在设计时与“属性”窗口广泛结合使用。 可以使用 TypeConverterAttribute 将类型转换器应用于属性或类型。
在属性上声明 TypeConverterAttribute
时,“属性”窗口使用转换器将属性显示为字符串值。 在类型上声明 TypeConverterAttribute
时,“属性”窗口对该类型的每个属性使用转换器。 类型转换器还有助于序列化设计器的代码隐藏文件中的属性值。
类型编辑器
当属性的类型为内置类型或已知类型时,“属性”窗口自动对属性使用类型编辑器。 例如,布尔值被编辑为 True 和 False 值的组合框,DateTime 类型使用日历下拉列表。
重要
自 .NET Framework 以来,自定义类型编辑器已更改。 有关详细信息,请参阅自 .NET Framework(Windows 窗体 .NET)以来的设计器更改。