如何在项目中的所有文本框中添加(gotfocus - lostfocus)事件



我在一年前创建了一个项目,现在我想为所有聚焦的文本框添加背景色。我知道我可以为所有文本框创建事件,但这将花费很多时间,我知道我可以创建一个自定义控件(文本框),但我不喜欢。所以我可以为我的项目中的所有文本框添加这些事件吗?

让我们来看看所有的可能性。

首先,处理事件的通常做法是为每个控件的每个事件创建一个不同的处理程序,例如
Private Sub TextBox1_Enter(sender As Object, e As EventArgs) Handles TextBox1.Enter
'...
End Sub
Private Sub TextBox1_Leave(sender As Object, e As EventArgs) Handles TextBox1.Leave
'...
End Sub
Private Sub TextBox2_Enter(sender As Object, e As EventArgs) Handles TextBox2.Enter
'...
End Sub
Private Sub TextBox2_Leave(sender As Object, e As EventArgs) Handles TextBox2.Leave
'...
End Sub

如果你对每个控件的相同事件做同样的事情,你可以将其压缩为每个事件的单个事件处理程序:

Private Sub TextBoxes_Enter(sender As Object, e As EventArgs) Handles TextBox1.Enter, TextBox2.Enter
Dim tb = DirectCast(sender, TextBox)
'...
End Sub
Private Sub TextBoxws_Leave(sender As Object, e As EventArgs) Handles TextBox1.Leave, TextBox2.Leave
Dim tb = DirectCast(sender, TextBox)
'...
End Sub

sender参数指向引发事件的对象,因此您可以通过强制转换访问适当的TextBox。你处理的事件的对象不必是相同的类型,你甚至可以用一个方法处理多个事件,只要签名是兼容的:

Private Sub Controls_FocusChanged(sender As Object, e As EventArgs) Handles TextBox1.Enter,
      TextBox2.Enter,
      ComboBox1.Enter,
      TextBox1.Leave,
      TextBox2.Leave,
      ComboBox1.Leave
Dim cntrl = DirectCast(sender, Control)
'The event is raised before the change happens so the control
'will have focus on Leave and will not have focus on Enter.
cntrl.BackColor = If(cntrl.Focused, SystemColors.Window, Color.Yellow)
End Sub

请注意,设计器可以帮助您完成此操作。您可以选择多个控件,打开Properties窗口,单击Events按钮,然后双击所需的事件,为Handles子句中所有选定的控件生成具有选定事件的单个事件处理程序。然后,您可以在下拉列表中为一个或多个控件的另一个事件选择现有的事件处理程序,并将其添加到Handles子句中。您可以根据需要在代码窗口中编辑方法名称。如果你愿意,你也可以自己编写方法和Handles子句。

其次,要在每个表单中编写更少的代码,您可以将事件处理程序放在某个模块中,然后使用AddHandler语句将其附加到表单加载时的事件:

Module CommonEventHandlers
Public Sub Controls_FocusChanged(sender As Object, e As EventArgs)
Dim cntrl = DirectCast(sender, Control)
'The control will have focus on Leave and will not have focus on Enter.
cntrl.BackColor = If(cntrl.Focused, SystemColors.Window, Color.Yellow)
End Sub
End Module

:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
For Each tb In Controls.OfType(Of TextBox)()
AddHandler tb.Enter, AddressOf CommonEventHandlers.Controls_FocusChanged
AddHandler tb.Leave, AddressOf CommonEventHandlers.Controls_FocusChanged
Next
End Sub
Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
For Each tb In Controls.OfType(Of TextBox)()
RemoveHandler tb.Enter, AddressOf CommonEventHandlers.Controls_FocusChanged
RemoveHandler tb.Leave, AddressOf CommonEventHandlers.Controls_FocusChanged
Next
End Sub

将处理直接添加到表单中的所有TextBoxes的事件。如果你想要不同的控件和/或一些在子容器中,那么你需要相应地调整。请注意,当您完成后需要删除事件处理程序。

最后,属性"解决方案是使用自定义控件。您只需向项目添加一个类,然后向该类添加Inherits行即可创建自定义控件。然后,您可以为您原本要处理的事件重写适当的方法,例如OnEnter方法用于Enter事件。方法中的代码与事件处理程序中的代码基本相同,只是它指向当前对象而不是sender:

Public Class TextBoxEx
Inherits TextBox
Private defaultBackColor As Color
''' <inheritdoc />
Protected Overrides Sub OnEnter(e As EventArgs)
defaultBackColor = BackColor
BackColor = Color.Yellow
MyBase.OnEnter(e)
End Sub
''' <inheritdoc />
Protected Overrides Sub OnLeave(e As EventArgs)
BackColor = defaultBackColor
MyBase.OnLeave(e)
End Sub
End Class

你可以编辑现有表单的设计器代码文件来使用自定义控件而不是标准的TextBox,例如:

'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()
Me.TextBox1 = New System.Windows.Forms.TextBox()
Me.SuspendLayout()
'
'TextBox1
'
Me.TextBox1.Location = New System.Drawing.Point(0, 0)
Me.TextBox1.Name = "TextBox1"
Me.TextBox1.Size = New System.Drawing.Size(100, 20)
Me.TextBox1.TabIndex = 0
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(800, 450)
Me.Controls.Add(Me.TextBox1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents TextBox1 As TextBox

变成这样:

'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()
Me.TextBox1 = New TextBoxEx()
Me.SuspendLayout()
'
'TextBox1
'
Me.TextBox1.Location = New System.Drawing.Point(0, 0)
Me.TextBox1.Name = "TextBox1"
Me.TextBox1.Size = New System.Drawing.Size(100, 20)
Me.TextBox1.TabIndex = 0
'
'Form1
'
Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.ClientSize = New System.Drawing.Size(800, 450)
Me.Controls.Add(Me.TextBox1)
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
Me.PerformLayout()
End Sub
Friend WithEvents TextBox1 As TextBoxEx

每个控件只更改了两行代码,您可以使用查找&替换功能。一切看起来和工作都和以前一样,但是你的TextBoxes会自动显示新的行为。一旦您构建了项目,自定义控件将被添加到工具箱,因此您可以将其添加到设计器中的窗体中,就像任何其他控件一样。

请注意,为了访问设计器代码文件,您需要在解决方案资源管理器中选择您的项目或其中的一个项,并单击显示所有文件按钮。然后可以展开窗体的节点并打开设计器代码文件。

最新更新