David Gard
David Gard

Reputation: 12087

Handle an event of a control defined on another form

I have a form declared as s property WithEvents. If I add Handles formServers.FormClosing to a Sub declaration it works fine, but when I want to handle an event of a control within formServers I get the following error -

'Handles' in classes must specify a 'WithEvents' variable.

How do I correctly set this up? Thanks.

Private WithEvents formServers As New formServers    

Private Sub txtServers_Closing(ByVal Sender As Object,
                                ByVal e As EventArgs) Handles formServers.txtServers.LostFocus

    Me.SetServers()

    If Me.ServersError Then
        Dim Ex As New Exception("Error validating Servers.")
        Dim ErrorForm = New formError(Ex, 101)
    End If

End Sub

Upvotes: 1

Views: 2865

Answers (2)

Steven Doggart
Steven Doggart

Reputation: 43743

The problem is that you do are not specifying WithEvents on the TextBox. Rather, you are specifying WithEvents on the Form. You can only use Handles on variables which you have declared directly with the WithEvents keyword. With the WithEvents being on the form, you will only be able to use Handles to handle events that are raised directly by the form itself. You will not be able to do so for events raised by any of its controls.

You can fix this in one of two ways. Either you can use AddHandler to register your event handler (rather than using the Handles keyword), or you can create a TextBox variable WithEvents and then set it to the appropriate TextBox object on the form, like this.

Private formInstance As New FormServers 
Private WithEvents txtServers As TextBox

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    txtServers = formServers.txtServers
End Sub

Private Sub txtServers_LostFocus(Sender As Object, e As EventArgs) Handles txtServers.LostFocus
    ' ...
End Sub

The advantage of the latter approach, besides the more consistent, and possibly more elegant syntax, is that you don't have to remember to call RemoveHandler.

Upvotes: 1

Hans Passant
Hans Passant

Reputation: 942338

The error message is fairly misleading. The Handles keyword has several restrictions, it cannot work across different classes, it needs an object reference. You must use the more universal AddHandler keyword instead.

There are some additional problems in your scenario. Never use the LostFocus event, use Leave instead. And it is very important that you subscribe the event for the specific instance of the form, using As New gets you into trouble when you display the form multiple times, an ObjectDisposedException will be the outcome. Correct code looks like this:

Private formInstance As FormServers 

Private Sub DisplayFormServer()
    formInstance = new FormServers
    AddHandler formInstance.txtServers.Leave, AddressOf txtServers_Closing
    AddHandler formInstance.FormClosed, _
        Sub()
            formInstance = Nothing
        End Sub
    formInstance.Show()
End Sub

A much more elegant approach is to expose the event explicitly in your FormServers class. Make that look like this:

Public Class FormServers
    Public Event ServersLeave As EventHandler

    Private Sub txtServers_Leave(sender As Object, e As EventArgs) Handles txtServers.Leave
        RaiseEvent ServersLeave(Me, EventArgs.Empty)
    End Sub
End Class

Upvotes: 3

Related Questions