Sometimes you want to call methods on a WinForms control (for example) but not have it raise events, e.g. to prevent recursive calls. For handlers you've added yourself with AddHandler, the answer is obvious: remove the handler and re-add it when you've done your thing. However, in VB you've usually got automatically generated event handlers hooked up to WithEvents fields with the Handles keyword. What do you do about these? Is it OK to call Remove/AddHandler in the usual way?
(BTW I think the alternative technique of setting an "ignore events" flag is to be discouraged because it has to be tested in all of the handlers; by using Add/RemoveHandler you're keeping the code close to the point that requires it.)
The WithEvents section in the Language Spec is quite revealing on this point.
Basically, if you declare a WithEvents variable called x, what you actually get is a private variable called _x and a property called x that looks like this:
Friend Overridable Property x() As TextBox
Get
Return _x
End Get
Set(ByVal value As TextBox)
If _x IsNot Nothing Then
'Remove handlers from _x
End If
_x = value
If _x IsNot Nothing Then
'Add handlers to _x
End If
End Set
End Property
The list of handlers to add and remove is generated from all the methods that have a "Handles" clause for an event of this instance. If a WithEvents field has no handlers, the wrapper property is still generated but its setter simply sets the value of the hidden field.
Knowing this, you can temporarily suspend all event handling (other than via handlers you explicitly added yourself) with code like this:
Dim temp As TextBox = x
x = Nothing
temp.AppendText() 'Anything that would normally raise an event
x = temp
Caveat: the code between setting x to Nothing and restoring it can't call any methods that need to access x; also, this code should be wrapped in a Try/Finally to make sure the field is always reset to its original value.
No comments:
Post a Comment