扩展控件可以从任何.NET Compact Framework现有的Windows窗体控件继承而来。扩展控件可以保留Windows窗体控件所有的固有功能,然后通过添加自定义属性、方法或事件来进行功能扩展,这也是扩展控件名称的由来。扩展控件有两个优点,第一,可以很容易的创建;第二,通过继承使开发工作事半功倍。因此针对下列情况建议采用扩展控件:
· 可以利用现有Windows窗体控件已经包含的大多数所需的功能。
· 不需要自定义控件图形界面,或者想为现有控件设计一个新的图形用户界面。
例如,如果希望创建一个从TextBox继承而来的扩展控件,则新扩展控件不但外观和操作方式与TextBox控件完全一样,还可以添加自定义的控件逻辑。
创建扩展控件
扩展控件源自Windows窗体控件,比如TextBox、ListBox或Button。对所继承控件的选择直接决定扩展控件本身所具有的属性、方法以及事件。要创建扩展控件可以在Visual Studio 2005里选择“类库”模板。
创建扩展控件首先需要创建一个类库项目。Visual Studio 2005创建类库项目后会自动创建一个类模块,默认的类模块名为Class1。这里以TextBox为父类来创建扩展控件为例进行介绍。清单8-4展示了一个空的类模块。
清单8-4 空的类模块
Public Class TextBoxPlus
End Class
在这个类模块里,类名为TextBoxPlus。这意味着在使用这个类的时候,可以通过以下代码申明并实例化该类:
Dim WithEvents txtDemo As New TextBoxPlus
创建了类模块之后,可以选择从System.Windows.Forms.Control类继承,还是选择从现有的Windows窗体控件直接继承。因为System.Windows.Forms.Control类是比较底层的控件类,为了简化开发常常选择直接继承现有的Windows窗体控件,例如,清单8-5演示了从TextBox控件直接继承实现TextBoxPlus扩展控件。
清单8-5 继承TextBox控件实现TextBoxPlus扩展控件
Public Class TextBoxPlus
Inherits System.Windows.Forms.TextBox
End Class
添加控件属性
添加控件属性的过程可简可繁,这取决于希望实现怎样的功能。例如,想为TextBoxPlus扩展控件增加属性,需要执行下列步骤:
(1)在解决方案资源管理器中,右击扩展控件文件,例如TextBoxPlus.vb,然后在弹出式快捷菜单上单击“查看类关系图”菜单项,打开表示类关系图的视图,如图8-9所示。注意扩展控件的类关系图显示TextBoxPlus从TextBox继承而来,这是与复合控件在类关系图上的差别。
(2)右击该类关系图,在弹出式快捷菜单上单击“类详细信息”菜单项。
(3)在“类详细信息”窗口的“属性”部分中,在“<添加属性>”提示下,键入属性名称MyProperty。
(4)在“类型”列中,输入String类型。
(5)右击MyProperty所在行最左边的图标,然后在弹出式快捷菜单上单击“属性”菜单项。
(6)若要指定“自定义属性”的属性值,则在“属性”窗口中单击“自定义属性”项最左边的按钮,以打开如图8-6所示的“自定义属性”对话框。
(7)键入 Browsable(true),单击“确定”按钮,来设置该属性在设计时的属性窗口中可见。
(8)此时,可以在解决方案资源管理器中,查看包含该自定义属性的设计时属性.xmta文件DesignTimeAttributes.xmta。
(9)添加该属性的定义代码,清单8-6演示了该属性的定义代码。如果需要也可以创建只读属性,清单8-7演示了只读属性的定义代码。
清单8-6 MyProperty属性定义代码
Private tmpProperty As String
Public Property MyProperty() As String
Get
Return tmpProperty
End Get
Set(ByVal value As String)
tmpProperty = value
End Set
End Property
清单8-7 只读属性定义代码
Private mCount As Integer
Public ReadOnly Property Count() As Integer
Get
Count = mCount
End Get
End Property
添加集合属性
为了向扩展控件添加集合属性,首先需要创建一个定义集合功能的类,然后添加一个属性并将之前创建的定义集合功能的类做为属性的类型。
清单8-8演示了添加集合属性的过程。在清单8-8里,定义了一个继承于Control的Scheduler类,并为Scheduler类添加一个Item属性,然后又定义了一个命名为ScheduleItem的普通的类,并将ScheduleItem类申明为Scheduler类Item属性的属性类型。
清单8-8 添加集合属性
Public Class Scheduler
Inherits Control
Public Items As New ScheduleItem
End Class
Public Class ScheduleItem
Structure LaunchItem
Dim Application As String
Dim Arguments As String
Dim LaunchTime As Date
End Structure
Private mItems As New Collection
Public ReadOnly Property Count() As Integer
Get
Count = mItems.Count
End Get
End Property
Public ReadOnly Property Item(ByVal Index As Integer) As LaunchItem
Get
Item = mItems.Item(Index)
End Get
End Property
Public Sub Add(ByVal Item As LaunchItem)
mItems.Add(Item)
End Sub
Public Sub Clear()
While mItems.Count > 0
mItems.Remove(1)
End While
End Sub
End Class
控制属性值
有时为了特殊的功能,需要对自定义控件添加的属性进行限制。有两种方法可以控制属性值,一种是通过属性的数据类型来限制,另一种是在定义属性的Set部分添加代码控制属性值。
1. 通过枚举类型控制属性值
通过枚举数据类型来控制属性值是一个简单的办法。清单8-9演示了这种办法。在清单8-9所示代码的开始部分定义了一个具有五个枚举值的枚举数据类型Values,然后声明Rating属性。这段代码的关键之处就是采用枚举数据类型定义属性的数据类型,限制了属性的取值范围。
清单8-9 使用枚举数据类型
……
Enum Values
Excellent = 5
Good = 4
Average = 3
BelowAverage = 2
Poor = 1
Bad = 0
End Enum
Private Dim mRating As Values
Public Property Rating() As Values
Get
Rating = mRating
End Get
Set(ByVal Value As Values)
mRating = Value
End Set
End Property
……
图8-10展示如何使用枚举类型的属性。
图8-10 使用枚举类型的属性
2. 编写属性值控制代码
第二种控制属性值的方法是在定义属性的Set部分添加控制代码。清单8-10演示一个添加了控制代码的属性定义过程。通过为属性添加的控制代码,可以简单的检查并拒绝无效属性值。图8-11展示了控制代码阻止无效属性值而抛出例外的执行结果。
清单8-10 增加了控制的属性定义
Private nRating As Integer
Public Property Rating1() As Integer
Get
Rating = nRating
End Get
Set(ByVal Value As Integer)
If (Value > 5) Or (Value < 0) Then
Err.Raise(vbObjectError + 1234, "错误", "My God——Rating1属性被赋予非法属性值!")
Else
nRating = Value
End If
End Set
End Property
图8-11 属性控制代码执行结果
属性的错误处理
清单8-10演示了属性值的错误处理。这种处理是非常重要的,因为在开发自定义控件时,需要确保所开发的控件是正确可靠的。在属性定义过程中添加错误处理,可以向使用控件的开发者提供反馈。这是属性错误例外处理的意义所在。
属性错误例外处理的语法结构如下:
Err.Raise(number, source, description, helpfile, helpcontent)
Err.Raise()生成一个运行时错误。表8-1列出了Err.Raise()参数的详细说明。
表8-1 Err.Raise()参数表
参数 | 说明 |
Number | 必选。标识错误特性的Long整型。Visual Basic错误处于0~65535的范围内:范围0~512保留用于系统错误,范围513~65535则用于用户定义的错误。当在类模块中将Number属性设置为您自己的错误代码时,将错误代码号添加到vbObjectError常数。例如,若要生成错误号513,应将vbObjectError + 513分配给Number属性 |
Source | 可选。命名生成错误的对象的字符串。如果没有指定Source,则使用当前Visual Basic项目的进程ID |
(续表)
参数 | 说明 |
Description | 可选。描述错误的字符串。如果未指定,则检查Number属性值。如果它可以映射到Visual Basic运行时错误代码,则将Error函数要返回的字符串用作Description属性。如果没有对应于Number属性的Visual Basic错误,则使用“应用程序定义的错误或对象定义的错误”消息 |
HelpFile | 可选。帮助文件的完全限定路径,在该文件中可找到此错误的帮助信息。如果未指定HelpFile参数,则Visual Basic使用Visual Basic帮助文件的完全限定的驱动器、路径和文件名 |
HelpContent | 可选。上下文ID,标识HelpFile中提供错误帮助的主题。如果省略该参数,则使用与Number属性对应的错误的Visual Basic帮助文件上下文ID(如果有) |
重载控件属性
除了添加自定义属性外,开发人员也可以修改控件继承而来的属性。例如,修改任何继承控件的Text属性,仅仅需要为属性声明增加关键字Overrides。清单8-11演示了这项编程技巧。
清单8-11 重载控件属性
Private mText As String
Public Overrides Property Text() As String
Get
Return mText
End Get
Set(ByVal Value As String)
mText = Value
End Set
End Property
重载属性的好处是能够继承现有控件属性的所有功能和特征,并在此基础上添加自定义的功能代码。
添加控件方法
为扩展控件添加自定义方法,实际就是为扩展控件定义公有的过程或函数。以MyMethod方法为例,需要执行下列步骤:
(1)在解决方案资源管理器中,右击扩展控件文件,例如TextBoxPlus.vb,然后在弹出式快捷菜单上单击“查看类关系图”菜单项,打开类关系设计视图,如图8-12所示。
(2)右击该类关系图,在弹出式快捷菜单上单击“类详细信息”菜单项。
(3)在“类详细信息”窗口的“方法”部分中,在“<添加方法>”提示下,键入方法名称MyMethod。
(4)在“类型”列中,输入String类型。
(5)最后添加该方法的定义代码,清单8-12演示了该方法定义代码。
清单8-12 MyMethod方法定义代码
Public Function MyMethod() As String
Return “扩展控件自定义方法”
End Function
重载控件方法
重载扩展控件的方法与重载扩展控件属性有所不同,为了重载扩展控件的方法首先要确定该方法可被重载。.NET Compact Framework的Windows窗体控件只有少数的方法或过程可被重载。清单8-13展示了重载控件方法的代码,注意与定义普通方法相比,增加了关键字Overrides。
清单8-13 重载控件方法
Public Overrides Sub Refresh()
……
End Sub
隐藏控件方法
在有些情况下,希望用扩展控件的方法替换父类控件的对应方法,但是父类控件的对应方法又不能被重载,这时可以在扩展控件中隐藏父类控件对应的方法。
为了隐藏父类控件方法,可以在声明方法的代码部分增加关键字Shadows。清单8-14展示了隐藏控件方法的代码。.NET Compact Framework的Windows窗体控件的Show方法不能不重载,但是可以采用隐藏该方法的方式实现替换父类控件对应方法的功能。
清单8-14 隐藏控件方法
Public Shadows Sub Show()
……
End Sub
添加控件事件
添加一个扩展控件事件的过程包括:声明事件和实现事件。以MyEvent事件为例,添加一个扩展控件事件需要执行下列步骤:
(1)在解决方案资源管理器中,右击复合控件文件,例如TextBoxPlus.vb,然后在弹出式快捷菜单上单击“查看类关系图”菜单项,打开类关系设计视图。
(2)右击该类关系图,在弹出式快捷菜单上单击“类详细信息”菜单项。
(3)在“类详细信息”窗口的“事件”部分中,在“<添加事件>”提示下,键入事件名称MyEvent。
(4)右击MyEvent所在行最左边的图标,然后在弹出式快捷菜单上单击“属性”菜单项。
(5)若要指定“自定义属性”属性的值,则在“属性”窗口中单击“自定义属性”项最左边的按钮,以打开如图8-13所示的“自定义属性”对话框。
(6)键入Browsable(true),单击“确定”按钮来设置该事件在设计时的属性窗口中可见。
(7)此时,可以在解决方案资源管理器中,查看包含该自定义事件的设计时属性.xmta文件DesignTimeAttributes.xmta。
(8)最后添加该事件的定义代码,清单8-15演示了该事件的定义代码。
清单8-15 MyEvent事件定义代码
Public Event MyEvent As EventHandler
Private Sub myGotFocus(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.GotFocus
RaiseEvent MyEvent(sender, e)
End Sub
自定义事件一般通过父类控件的事件来触发。在清单8-15中,通过父类控件的GotFocus来触发自定义事件MyEvent。
重载控件事件
重载控件事件可以补充或替换父类控件的事件。重载控件事件要求使用与父类控件的事件完全相同的参数列表。可以使用以下语法重载父类控件的事件:
Protected Overrides Sub EventName(By Vale EventArguments)
这里需要强调两点。第一,EventName由实际事件名加上前缀On组成,例如,重载TextBox控件的KeyDown事件,可以使用OnKeyDown作为事件名。重载TextBox控件的GotFocus事件,可以使用OnGotFocus作为事件名。第二,参数列表必须与父类控件的事件的参数列表完全一致,但除了sender参数。例如,清单8-16展示了TextBox控件KeyDown事件的声明。
清单8-16 TextBox的KeyDown事件
Private Sub TextBox1_KeyDown(ByVal sender As Object, _
ByVal e As System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown
……
End Sub
清单8-17显示KeyDown事件如何转变为重载事件的声明。清单8-17的关键之处是在两个事件声明中定义了相同的参数e。
清单8-17 重载TextBox的KeyDown事件
Protected Overrides Sub OnKeyDown(ByVal e As
System.Windows.Forms.KeyEventArgs)
……
End Sub
声明重载事件和其参数列表的最简单的方法就是获得原始事件的声明,然后删除sender参数。
使用扩展控件
创建完扩展控件并将其汇编入一个DLL文件之后,可以将它加入到Pocket PC应用程序中。下面是将扩展控件加入到一个Pocket PC应用程序中的步骤:
(1)创建一个.NET Compact Framework 2.0窗体应用程序项目。
(2)为Pocket PC应用程序添加扩展控件的引用。通过项目属性界面的引用标签页,添加包含扩展控件的DLL文件。在如图8-14所示的添加引用对话框里选择包含扩展控件的DLL文件,单击“确定”按钮后DLL文件包含的扩展控件自动添加到工具箱上。
(3)在工具箱中,找到自定义的扩展控件,然后拖放该扩展控件到窗体上。
(4)在“属性”窗口中,设置扩展控件的自定义属性。
(5)通过编写代码访问自定义属性和自定义方法,以及在自定义事件中添加代码。
扩展控件的演示代码可以在配套光盘本章所对应文件夹的InheritControlDemo项目中找到。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12641349/viewspace-150401/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/12641349/viewspace-150401/