VB.NET里面的Event机制(三)

前端之家收集整理的这篇文章主要介绍了VB.NET里面的Event机制(三)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

现在我们看看这样一个问题。我们想要做这样一个控件,他继承自Window.Forms.TextBox下面,也就是说它支持TextBox的所有功能,但是我们需要一个新的功能,就是当用户按下回车之后,我们判断一下这个TextBox里面的文字,如果是空字符串的话,就显示一个MessageBox,默认的内容是“Empty connect is not validated.”。同时我们希望用户可以选择是否显示这个MessageBox。我们用此前的办法来做。

我们的类很快就可以完成。

Public Class MyTextBox

Inherits TextBox

Public Event EnterKeyPress(ByVal sender As Object,ByRef Cancel As Boolean,ByRef Message As String)

Private Sub MyTextBox_KeyPress(ByVal sender As Object,ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress

'Do something then user press ENTER KEY

If Asc(e.KeyChar) = 13 Then

Dim Cancel As Boolean = False

Dim Message As String = "Empty connect is not validated."

'Send the event with parameters

RaiseEvent EnterKeyPress(Me,Cancel,Message)

'Show message Box depend on the return parameters

If Cancel = False Then

MsgBox(Message)

End If

End If

End Sub

End Class

而且我们很容易就可以使用这个控件了。

Public Class Form1

Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()

MyBase.New()

'This call is required by the Windows Form Designer.

InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.

Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

If disposing Then

If Not (components Is Nothing) Then

components.Dispose()

End If

End If

MyBase.Dispose(disposing)

End Sub

'required by the Windows Form Designer

Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer

'It can be modified using the Windows Form Designer.

'Do not modify it using the code editor.

<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

'

'Form1

'

Me.AutoScaleBaseSize = New System.Drawing.Size(5,12)

Me.ClientSize = New System.Drawing.Size(292,273)

Me.Name = "Form1"

Me.Text = "Form1"

End Sub

#End Region

Friend WithEvents MyTextBox1 As New MyTextBox

Private Sub Form1_Load(ByVal sender As System.Object,ByVal e As System.EventArgs) Handles MyBase.Load

Me.Controls.Add(Me.MyTextBox1)

Me.MyTextBox1.Location = New Point(100,100)

End Sub

Private Sub MyTextBox1_EnterKeyPress(ByVal sender As Object,ByRef Message As String) Handles MyTextBox1.EnterKeyPress

End Sub

End Class

现在看来一切正常,但是无聊的客户突然来了一个Mail,他们希望我们能够在显示MessageBox的时候,将TextBox的背景色变成红色,并且允许有可能在其它的时候会变成绿色。也就是说变色也是要使用者可以自由设定的。这样我们就要在Event参数列表里面加入一个新的背景色参数,并且修改所有使用了这个EventHandle函数

Public Class MyTextBox

Inherits TextBox

Public Event EnterKeyPress(ByVal sender As Object,ByRef Message As String,ByVal BackColor As Color)

Private Sub MyTextBox_KeyPress(ByVal sender As Object,ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress

'Do something then user press ENTER KEY

If Asc(e.KeyChar) = 13 Then

Dim Cancel As Boolean = False

Dim Message As String = "Empty connect is not validated."

Dim Color As Color = Color.Red

'Send the event with parameters

RaiseEvent EnterKeyPress(Me,Message,Color)

'Show message Box depend on the return parameters

If Cancel = False Then

MsgBox(Message)

End If

End If

End Sub

End Class

然后修改使用的地方,也许实际上我们只是让它显示成默认的红色,我们也需要修改使用Event的地方,因为Event的定义已经不同了。

Public Class Form1

Inherits System.Windows.Forms.Form

#Region " Windows Form Designer generated code "

Public Sub New()

MyBase.New()

'This call is required by the Windows Form Designer.

InitializeComponent()

'Add any initialization after the InitializeComponent() call

End Sub

'Form overrides dispose to clean up the component list.

Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)

If disposing Then

If Not (components Is Nothing) Then

components.Dispose()

End If

End If

MyBase.Dispose(disposing)

End Sub

'required by the Windows Form Designer

Private components As System.ComponentModel.IContainer

'NOTE: The following procedure is required by the Windows Form Designer

'It can be modified using the Windows Form Designer.

'Do not modify it using the code editor.

<System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()

'

'Form1

'

Me.AutoScaleBaseSize = New System.Drawing.Size(5,273)

Me.Name = "Form1"

Me.Text = "Form1"

End Sub

#End Region

Friend WithEvents MyTextBox1 As New MyTextBox

Private Sub Form1_Load(ByVal sender As System.Object,ByVal Color As Color) Handles MyTextBox1.EnterKeyPress

End Sub

End Class

现在我们只有这样一处使用这个Event的地方,但是假设我们有100Form,每个Form都有20个这样的TextBox(记住,你做的是通用控件,他可能会被用在任何的地方,会被使用上千次)。那么我们就要这样修改2000次。其中可能只有10个时需要把背景色变成别的颜色,比如耦合色。但是我还是要修改2000函数的。

当我们终于修改完成之后,客户有发来一封稍有歉意的Mail,说他们还希望能够设定MessageBox的按钮状态和显示属性,大部分是OKCancel按钮和Information形式,个别的是OK按钮和Error形式。看来我们有需要修改我们的TextBox类和那2000函数了。

而后,用户又来了一个Mail……天哪,看来我们有必要把Mail Service关掉了。因为这样修改对于项目是毁灭性的。我们有必要重新审视一下我们的TextBox类的建立问题了。

我们现在关键的问题就是参数,我们增加一点Event功能,就需要修改Event的参数列表,然后修改所有使用这个EventHandle函数。但是很多的时候,真正修改函数内部的地方可能很少,甚至没有。我们重复的劳动就是一个个修改Handle函数的参数列表。

那么我们看看.NET是怎么做的,我们看看Form.Closing事件Handle出来的函数

Private Sub Form1_Closing(ByVal sender As Object,ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing

End Sub

我们把注意力集中到第二个参数,它不是我们前面熟悉的EventArgs,而是CancelEventArgs。而我们看看这个CancelEventArgs里面都有什么。我们看到了e.Cancel.NET把我们此前做的那个Cancel参数通过第二个参数的成员属性传递进来了。这样我们就通过设定e.Cancel来达到我们原先的处理。

这里可能有的人会产生疑问,e参数被声明为ByVal,它应该不能被返回到RaiseEvent调用处的啊?但是事实是可以的。原因是.NET在处理类的实例参数的时候,传进来的不是实例本身,而是实例的指针。而我们ByVak的只不过是保存这个指针地址变量的一个副本。所以即使是ByVal,如果这个参数是类的实例,也可以把成员传递回去。

这样做的好处就是如果还有新的参数加入,我们只需要修改这个CancelEventArgs类和相应的RasiseEvent调用HandleEvent如果不需要对应这个新的参数,就没有必要修改了。这个就是面向对象的好处,封装了操作,只通过接口来连接。也就是软件工程里面所说的松耦合。

现在我们已找这个办法修改自己的TextBox类。首先我们要做好这个EventArgs类,模仿CancelEventArgs,我们做一个EnterKeyPressEventArgs

Public Class EnterKeyPressEventArgs

Inherits EventArgs

Private m_Cancel As Boolean

Private m_Message As String

Private m_BackColor As Color

Public Property Cancel() As Boolean

Get

Return m_Cancel

End Get

Set(ByVal Value As Boolean)

m_Cancel = Value

End Set

End Property

Public Property Message() As String

Get

Return m_Message

End Get

Set(ByVal Value As String)

m_Message = Value

End Set

End Property

Public Property BackColor() As Color

Get

Return m_BackColor

End Get

Set(ByVal Value As Color)

m_BackColor = Value

End Set

End Property

Public Sub New()

m_Cancel = False

m_Message = "Empty connect is not validated."

m_BackColor = Color.Red

End Sub

End Class

这个类继承自EventArgs,通过私有变量和公共属性来传递参数。为什么不用共有变量呢,有原因的,我心准备在专门写一篇文章说说这个问题。反正这样私有变量加公共属性的办法比公共变量要好。

然后我们修改TextBox类,调用RaiseEvent的地方就可以使用这个类了。

Public Event EnterKeyPress(ByVal sender As Object,ByVal e As EnterKeyPressEventArgs)

Private Sub MyTextBox_KeyPress(ByVal sender As Object,ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress

'Do something then user press ENTER KEY

If Asc(e.KeyChar) = 13 Then

'Create the args instance

Dim ekpea As New EnterKeyPressEventArgs

'Send the event with parameters

RaiseEvent EnterKeyPress(Me,ekpea)

'Show message Box depend on the return parameters

If ekpea.Cancel = False Then

Me.BackColor = ekpea.BackColor

MsgBox(ekpea.Message)

End If

End If

End Sub

我们使用的时候,也可以相应的修改成。

Private Sub MyTextBox1_EnterKeyPress(ByVal sender As Object,ByVal e As MyTextBox.EnterKeyPressEventArgs) Handles MyTextBox1.EnterKeyPress

'Some codes ...

e.Cancel = False

e.Message = "My message ... "

e.BackColor = Color.Green

'Some codes ...

End Sub

这样即便客户又来信说,我们需要加入一个功能,设定这个MessageBox的按钮类型,默认是VBOKOnlyInformation。我们需要修改的地方首先是这个EventArgs

Public Class EnterKeyPressEventArgs

Inherits EventArgs

Private m_Cancel As Boolean

Private m_Message As String

Private m_BackColor As Color

Private m_ButtonStyle As MsgBoxStyle

Public Property Cancel() As Boolean

Get

Return m_Cancel

End Get

Set(ByVal Value As Boolean)

m_Cancel = Value

End Set

End Property

Public Property Message() As String

Get

Return m_Message

End Get

Set(ByVal Value As String)

m_Message = Value

End Set

End Property

Public Property BackColor() As Color

Get

Return m_BackColor

End Get

Set(ByVal Value As Color)

m_BackColor = Value

End Set

End Property

Public Property Style() As MsgBoxStyle

Get

Return m_ButtonStyle

End Get

Set(ByVal Value As MsgBoxStyle)

m_ButtonStyle = Value

End Set

End Property

Public Sub New()

m_Cancel = False

m_Message = "Empty connect is not validated."

m_BackColor = Color.Red

m_ButtonStyle = MsgBoxStyle.OKOnly Or MsgBoxStyle.Information

End Sub

End Class

然后修改RaiseEvent的一句话。

MsgBox(ekpea.Message,ekpea.Style)

而使用的Handle函数只要使用默认值,就不需要修改了。

猜你在找的VB相关文章