要创建在运行时可读,但只能在设计时设置的属性,可以用属性过程实现。在 Property Let 或 Property Set 过程中,检查 AmbientProperties 对象的 UserMode 属性。如果 UserMode 是 True,则产生一个错误,如下面的代码段所示:
Private mdblSerendipity As Double Property Get Serendipity() As Double Serendipity = mdblSerendipity End Property Property Let Serendipity() As Double '
(省略了验证属性值的代码。)If Ambient.UserMode Then
Err.Raise Number:=382 _
Description:= _
" Let/Set not supported at run time."
End If
Serendipity = mdblSerendipity
PropertyChanged "Serendipity"
End Property
要在运行时完全禁止访问某个属性,可以在 Property Get 中产生“运行时属性不可用”错误。
注意 在实现 Variant 数据类型的属性时,需要全部的三个属性过程:Property Get、Property Let 和 Property Set,因为用户可以为此属性赋予包括对象引用在内的任何数据类型值。在这种情况下,Property Let 中产生的错误也必须在 Property Set 中产生。
下面的错误值是由 Visual Basic 提供的,应该被用于由只读和只写属性引起的错误:
Err.NumberErr.Description
382运行时不支持 Let/Set。
383设计时不支持 Let/Set。
393运行时不支持 Get。
394设计时不支持 Get。
一般情况下,建议在 ReadProperties 事件中将获取的值赋予属性,从而调用 Property Let。这将允许 Property Let 中的验证代码处理用户手工输入到容器源文件中的无效值,请参阅“保存属性”。
显然,这对于运行时只读的属性是个问题。解决的办法是跳过 Property Let,把获取的值直接赋给私有成员或子控件属性。如果属性只接受特定的值,则可以设计辅助函数,供 Property Let 和 ReadProperties 调用。
以下代码说明了这两种方案:
Private Sub UserControl_ReadProperties(PropBag As _ PropertyBag) '
总是使用ReadProperties
中的可捕获的错误!On Error Resume Next
'
获取HasWidgets
属性的值,'
它在运行时是只读的。mblnHasWidgets = _
PropBag.ReadProperty("HasWidgets", False)
If Err.Number <> 0 Then
'
如果.frm
文件包含使类型'
不匹配的值(错误13
),则'
用缺省值替换属性。mblnHasWidgets = False
' When using On Error Resume Next, always
' reset Err.Number after an error.
Err.Number = 0
End If
'
获取Appearance
属性的值,'
可在设计时设置它,'
并且有两个有效'
值,Appears3D
和AppearsFlat
。(应在
Public Enum
中'
定义这些常数。)mintAppearance = ValidateAppearance( _
PropBag.ReadProperty("Appearance", Appears3D))
'
验证由.frm
文件获取'
的值。Call ValidateAppearance(mintAppearance)
If Err.Number <> 0 Then
'
如果.frm
文件包含无效的'
整形值(错误380
)或使类型'
不匹配的值(错误13
),则'
用缺省值替换属性。mintAppearance = Appears3D
'
在使用On Error Resume Next
时,总要'
在错误之后复位Err.Number
。Err.Number = 0
End If
' . . .
其它属性. . .
End Sub
对于具有 Boolean、String 或一般的数字值类型属性,可以简单把值赋给私有成员,如上例中对 HasWidgets 属性那样处理。
Appearance 属性的 Property Let 将调用与上例相同的 ValidateAppearance 辅助函数,但不会捕获错误;于是,该错误将在指定了无效值的那个代码行出现。辅助函数看起来可能是这样的:
Private Sub ValidateAppearance(ByVal Test As Integer) Select Case Test Case Appears3D Case AppearsFlat Case Else '
错误380
是标准的“无效属性'
值”错误。Err.Raise 380
End Select
End Sub
重点 如果在源文件中输入了错误的数据类型,则会发生类型不匹配错误。于是,甚至对布尔属性或数值属性也可能引起错误。(这就是应该在 ReadProperties 中使用错误捕获的原因。)可以用 On Error Resume Next 捕获此错误,如上所示,并用缺省值替换属性。
要创建仅在运行时可用的属性,可以使属性过程在设计时(即 AmbientProperties 对象的 UserMode 属性为 False 时)无效。
Visual Basic 的“属性”窗口不会显示在设计时无效的属性。
提示 可以打开“过程属性”对话框,选择仅在运行时有效的属性,然后单击“高级”按钮,并选择“在属性浏览器中不显示”,从而防止“属性”窗口询问该属性。这就避免因为“属性”窗口询问该属性而进入中断方式,在调试设计时的行为时,该方式是很讨厌的。