Problem with Remove/AddHandle

L

Lloyd Sheen

I am trying to do the "Dot.Net" way of handling the following situation.

I have a handler for a textbox for changes in the text box. On the load of
the usercontrol containing the textbox I have the following code:

AddHandler ArtistName.TextChanged, AddressOf ArtistName_TextChanged

This works just fine. The problem is that in several occasions I want to
directly set the contents of the textbox and not have the event fire. In
the code to do this I have the following code:

RemoveHandler ArtistName.TextChanged, AddressOf ArtistName_TextChanged
Me.ArtistName.Text = inArtistName
AddHandler ArtistName.TextChanged, AddressOf ArtistName_TextChanged

This should first remove the handler such that the next line which sets the
text will not cause an event and then the handler is reinstated so that any
further keystrokes in the textbox will cause the event.

What happens is that on the first occurrence of the programmatic set of the
text there is no problem, the event does not happen but on each of the next
attempts the event is fired. I have verified this with the call stack.

Brand New Music
Console.exe!New_Music_Console.CDByArtistUC.ArtistName_TextChanged(Object
sender = {Text = "Laura Nyro"}, System.EventArgs e = {System.EventArgs})
Line 102 Basic
[External Code]
Brand New Music Console.exe!New_Music_Console.CDByArtistUC.setItems(String
inArtistName = "Laura Nyro") Line 96 + 0x25 bytes Basic
Brand New Music
Console.exe!New_Music_Console.MainForm.SongViewUC1_ShowArtistAlbums(String
artist = "Laura Nyro") Line 907 + 0x1b bytes Basic

I really don't want to create a Boolean to short-circuit the handler as I
want to use this technique in cases where the code is not necessarily in the
same code file.

LS
 
C

Cor Ligthert[MVP]

Lloyd,

I was currious to your problem, I made this piece of code, the only
difference I see that I did add the handler by using the VB extention for
that.
I did not have the problem you told. Can it be that your addhandler what you
asume is the load is executed more times?

\\\
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles TextBox1.TextChanged
Static x As Integer = 0
x += 1
Label1.Text = "I am changed for the " & x.ToString & " time"
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
RemoveHandler TextBox1.TextChanged, AddressOf TextBox1_TextChanged
Label1.Text = "I am reset"
TextBox1.Text = ""
AddHandler TextBox1.TextChanged, AddressOf TextBox1_TextChanged
End Sub
///

Cor



Lloyd Sheen said:
I am trying to do the "Dot.Net" way of handling the following situation.

I have a handler for a textbox for changes in the text box. On the load
of the usercontrol containing the textbox I have the following code:

AddHandler ArtistName.TextChanged, AddressOf ArtistName_TextChanged

This works just fine. The problem is that in several occasions I want to
directly set the contents of the textbox and not have the event fire. In
the code to do this I have the following code:

RemoveHandler ArtistName.TextChanged, AddressOf ArtistName_TextChanged
Me.ArtistName.Text = inArtistName
AddHandler ArtistName.TextChanged, AddressOf ArtistName_TextChanged

This should first remove the handler such that the next line which sets
the text will not cause an event and then the handler is reinstated so
that any further keystrokes in the textbox will cause the event.

What happens is that on the first occurrence of the programmatic set of
the text there is no problem, the event does not happen but on each of the
next attempts the event is fired. I have verified this with the call
stack.

Brand New Music
Console.exe!New_Music_Console.CDByArtistUC.ArtistName_TextChanged(Object
sender = {Text = "Laura Nyro"}, System.EventArgs e = {System.EventArgs})
Line 102 Basic
[External Code]
Brand New Music
Console.exe!New_Music_Console.CDByArtistUC.setItems(String inArtistName =
"Laura Nyro") Line 96 + 0x25 bytes Basic
Brand New Music
Console.exe!New_Music_Console.MainForm.SongViewUC1_ShowArtistAlbums(String
artist = "Laura Nyro") Line 907 + 0x1b bytes Basic

I really don't want to create a Boolean to short-circuit the handler as I
want to use this technique in cases where the code is not necessarily in
the same code file.

LS
 
L

Lloyd Sheen

Cor Ligthert said:
Lloyd,

I was currious to your problem, I made this piece of code, the only
difference I see that I did add the handler by using the VB extention for
that.
I did not have the problem you told. Can it be that your addhandler what
you asume is the load is executed more times?

\\\
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles TextBox1.TextChanged
Static x As Integer = 0
x += 1
Label1.Text = "I am changed for the " & x.ToString & " time"
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
RemoveHandler TextBox1.TextChanged, AddressOf TextBox1_TextChanged
Label1.Text = "I am reset"
TextBox1.Text = ""
AddHandler TextBox1.TextChanged, AddressOf TextBox1_TextChanged
End Sub
///

Cor



Lloyd Sheen said:
I am trying to do the "Dot.Net" way of handling the following situation.

I have a handler for a textbox for changes in the text box. On the load
of the usercontrol containing the textbox I have the following code:

AddHandler ArtistName.TextChanged, AddressOf ArtistName_TextChanged

This works just fine. The problem is that in several occasions I want to
directly set the contents of the textbox and not have the event fire. In
the code to do this I have the following code:

RemoveHandler ArtistName.TextChanged, AddressOf ArtistName_TextChanged
Me.ArtistName.Text = inArtistName
AddHandler ArtistName.TextChanged, AddressOf ArtistName_TextChanged

This should first remove the handler such that the next line which sets
the text will not cause an event and then the handler is reinstated so
that any further keystrokes in the textbox will cause the event.

What happens is that on the first occurrence of the programmatic set of
the text there is no problem, the event does not happen but on each of
the next attempts the event is fired. I have verified this with the call
stack.

Brand New Music
Console.exe!New_Music_Console.CDByArtistUC.ArtistName_TextChanged(Object
sender = {Text = "Laura Nyro"}, System.EventArgs e = {System.EventArgs})
Line 102 Basic
[External Code]
Brand New Music
Console.exe!New_Music_Console.CDByArtistUC.setItems(String inArtistName
= "Laura Nyro") Line 96 + 0x25 bytes Basic
Brand New Music
Console.exe!New_Music_Console.MainForm.SongViewUC1_ShowArtistAlbums(String
artist = "Laura Nyro") Line 907 + 0x1b bytes Basic

I really don't want to create a Boolean to short-circuit the handler as I
want to use this technique in cases where the code is not necessarily in
the same code file.

LS

Cor,

Could you add the code to your sample and see what you get. It uses linq
for the search so if you are not using VS 2008 you will have to change the
query to a loop.
You will need -

Imports System.ComponentModel
Imports System.Reflection
Imports System.Data.Linq



Public Function GetEventSubscribers(ByVal target As Object, ByVal eventName
As String) As [Delegate]()
Dim t As Type = target.GetType
Dim fia As FieldInfo() = t.GetFields((BindingFlags.NonPublic Or
(BindingFlags.Static Or BindingFlags.Instance)))
For Each f As FieldInfo In fia
Debug.WriteLine(f.Name)
Next
Dim q() As FieldInfo = (From fif In fia Where
fif.Name.Contains(eventName.ToUpper) Select fif).ToArray
If q.Count > 0 Then
Dim fi As FieldInfo
Dim d As [Delegate]
fi = q(0)
d = TryCast(fi.GetValue(target), [Delegate])
If (Not d Is Nothing) Then
Return d.GetInvocationList
End If
End If
Return New [Delegate](0 - 1) {}
End Function

When I use this with my TextBox (see below) it does not find the TextChange
event. I have tried other controls and they seem to find all the events.

Dim tmpDelegates() As [Delegate]
tmpDelegates = GetEventSubscribers(Me.ArtistName, "TextChange")

One last thing. The Textbox is in a usercontrol, hosted in a tabpage,
hosted on the mainform. I have had many problems with tabs including
docking where I have had to code the docking in the maninform load event.

Thanks
LS
 
C

Cor Ligthert[MVP]

Lloyd,
One last thing. The Textbox is in a usercontrol, hosted in a tabpage,
hosted on the mainform. I have had many problems with tabs including
docking where I have had to code the docking in the maninform load event.

Afaik is the tabpage doing a kind of initializing everytime it is from not
showed to showed. (Herfried knows this much better then I)

Therefore can you first delete the add handler from your load and simple
set it in the event sub in VB style (or just for testing set a boolean
before that initial load.)

Cor

Lloyd Sheen said:
Cor Ligthert said:
Lloyd,

I was currious to your problem, I made this piece of code, the only
difference I see that I did add the handler by using the VB extention for
that.
I did not have the problem you told. Can it be that your addhandler what
you asume is the load is executed more times?

\\\
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles TextBox1.TextChanged
Static x As Integer = 0
x += 1
Label1.Text = "I am changed for the " & x.ToString & " time"
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
RemoveHandler TextBox1.TextChanged, AddressOf TextBox1_TextChanged
Label1.Text = "I am reset"
TextBox1.Text = ""
AddHandler TextBox1.TextChanged, AddressOf TextBox1_TextChanged
End Sub
///

Cor



Lloyd Sheen said:
I am trying to do the "Dot.Net" way of handling the following situation.

I have a handler for a textbox for changes in the text box. On the load
of the usercontrol containing the textbox I have the following code:

AddHandler ArtistName.TextChanged, AddressOf ArtistName_TextChanged

This works just fine. The problem is that in several occasions I want
to directly set the contents of the textbox and not have the event fire.
In the code to do this I have the following code:

RemoveHandler ArtistName.TextChanged, AddressOf ArtistName_TextChanged
Me.ArtistName.Text = inArtistName
AddHandler ArtistName.TextChanged, AddressOf ArtistName_TextChanged

This should first remove the handler such that the next line which sets
the text will not cause an event and then the handler is reinstated so
that any further keystrokes in the textbox will cause the event.

What happens is that on the first occurrence of the programmatic set of
the text there is no problem, the event does not happen but on each of
the next attempts the event is fired. I have verified this with the
call stack.

Brand New Music
Console.exe!New_Music_Console.CDByArtistUC.ArtistName_TextChanged(Object
sender = {Text = "Laura Nyro"}, System.EventArgs e = {System.EventArgs})
Line 102 Basic
[External Code]
Brand New Music
Console.exe!New_Music_Console.CDByArtistUC.setItems(String inArtistName
= "Laura Nyro") Line 96 + 0x25 bytes Basic
Brand New Music
Console.exe!New_Music_Console.MainForm.SongViewUC1_ShowArtistAlbums(String
artist = "Laura Nyro") Line 907 + 0x1b bytes Basic

I really don't want to create a Boolean to short-circuit the handler as
I want to use this technique in cases where the code is not necessarily
in the same code file.

LS

Cor,

Could you add the code to your sample and see what you get. It uses linq
for the search so if you are not using VS 2008 you will have to change the
query to a loop.
You will need -

Imports System.ComponentModel
Imports System.Reflection
Imports System.Data.Linq



Public Function GetEventSubscribers(ByVal target As Object, ByVal
eventName As String) As [Delegate]()
Dim t As Type = target.GetType
Dim fia As FieldInfo() = t.GetFields((BindingFlags.NonPublic Or
(BindingFlags.Static Or BindingFlags.Instance)))
For Each f As FieldInfo In fia
Debug.WriteLine(f.Name)
Next
Dim q() As FieldInfo = (From fif In fia Where
fif.Name.Contains(eventName.ToUpper) Select fif).ToArray
If q.Count > 0 Then
Dim fi As FieldInfo
Dim d As [Delegate]
fi = q(0)
d = TryCast(fi.GetValue(target), [Delegate])
If (Not d Is Nothing) Then
Return d.GetInvocationList
End If
End If
Return New [Delegate](0 - 1) {}
End Function

When I use this with my TextBox (see below) it does not find the
TextChange event. I have tried other controls and they seem to find all
the events.

Dim tmpDelegates() As [Delegate]
tmpDelegates = GetEventSubscribers(Me.ArtistName, "TextChange")

One last thing. The Textbox is in a usercontrol, hosted in a tabpage,
hosted on the mainform. I have had many problems with tabs including
docking where I have had to code the docking in the maninform load event.

Thanks
LS
 
L

Lloyd Sheen

Cor Ligthert said:
Lloyd,
One last thing. The Textbox is in a usercontrol, hosted in a tabpage,
hosted on the mainform. I have had many problems with tabs including
docking where I have had to code the docking in the maninform load event.

Afaik is the tabpage doing a kind of initializing everytime it is from not
showed to showed. (Herfried knows this much better then I)

Therefore can you first delete the add handler from your load and simple
set it in the event sub in VB style (or just for testing set a boolean
before that initial load.)

Cor

Lloyd Sheen said:
Cor Ligthert said:
Lloyd,

I was currious to your problem, I made this piece of code, the only
difference I see that I did add the handler by using the VB extention
for that.
I did not have the problem you told. Can it be that your addhandler what
you asume is the load is executed more times?

\\\
Private Sub TextBox1_TextChanged(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles TextBox1.TextChanged
Static x As Integer = 0
x += 1
Label1.Text = "I am changed for the " & x.ToString & " time"
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
RemoveHandler TextBox1.TextChanged, AddressOf
TextBox1_TextChanged
Label1.Text = "I am reset"
TextBox1.Text = ""
AddHandler TextBox1.TextChanged, AddressOf TextBox1_TextChanged
End Sub
///

Cor



I am trying to do the "Dot.Net" way of handling the following situation.

I have a handler for a textbox for changes in the text box. On the
load of the usercontrol containing the textbox I have the following
code:

AddHandler ArtistName.TextChanged, AddressOf ArtistName_TextChanged

This works just fine. The problem is that in several occasions I want
to directly set the contents of the textbox and not have the event
fire. In the code to do this I have the following code:

RemoveHandler ArtistName.TextChanged, AddressOf ArtistName_TextChanged
Me.ArtistName.Text = inArtistName
AddHandler ArtistName.TextChanged, AddressOf ArtistName_TextChanged

This should first remove the handler such that the next line which sets
the text will not cause an event and then the handler is reinstated so
that any further keystrokes in the textbox will cause the event.

What happens is that on the first occurrence of the programmatic set of
the text there is no problem, the event does not happen but on each of
the next attempts the event is fired. I have verified this with the
call stack.

Brand New Music
Console.exe!New_Music_Console.CDByArtistUC.ArtistName_TextChanged(Object
sender = {Text = "Laura Nyro"}, System.EventArgs e =
{System.EventArgs}) Line 102 Basic
[External Code]
Brand New Music
Console.exe!New_Music_Console.CDByArtistUC.setItems(String
inArtistName = "Laura Nyro") Line 96 + 0x25 bytes Basic
Brand New Music
Console.exe!New_Music_Console.MainForm.SongViewUC1_ShowArtistAlbums(String
artist = "Laura Nyro") Line 907 + 0x1b bytes Basic

I really don't want to create a Boolean to short-circuit the handler as
I want to use this technique in cases where the code is not necessarily
in the same code file.

LS

Cor,

Could you add the code to your sample and see what you get. It uses linq
for the search so if you are not using VS 2008 you will have to change
the query to a loop.
You will need -

Imports System.ComponentModel
Imports System.Reflection
Imports System.Data.Linq



Public Function GetEventSubscribers(ByVal target As Object, ByVal
eventName As String) As [Delegate]()
Dim t As Type = target.GetType
Dim fia As FieldInfo() = t.GetFields((BindingFlags.NonPublic Or
(BindingFlags.Static Or BindingFlags.Instance)))
For Each f As FieldInfo In fia
Debug.WriteLine(f.Name)
Next
Dim q() As FieldInfo = (From fif In fia Where
fif.Name.Contains(eventName.ToUpper) Select fif).ToArray
If q.Count > 0 Then
Dim fi As FieldInfo
Dim d As [Delegate]
fi = q(0)
d = TryCast(fi.GetValue(target), [Delegate])
If (Not d Is Nothing) Then
Return d.GetInvocationList
End If
End If
Return New [Delegate](0 - 1) {}
End Function

When I use this with my TextBox (see below) it does not find the
TextChange event. I have tried other controls and they seem to find all
the events.

Dim tmpDelegates() As [Delegate]
tmpDelegates = GetEventSubscribers(Me.ArtistName, "TextChange")

One last thing. The Textbox is in a usercontrol, hosted in a tabpage,
hosted on the mainform. I have had many problems with tabs including
docking where I have had to code the docking in the maninform load event.

Thanks
LS

Cor,

The tabpage is loaded on form load, the user control I use has only one
occurence of the load and that is where I set the handler. I have done a
bunch of testing using reflection and it really appears that the textbox
does not in any way I can see follow the rules as do other controls. I may
be my understanding (or lack of) of reflection but I had to create a Type
object of the base type to see the events and fields for the TextBox object.
This may be why.

I guess the boolean will have to do for now and I will have to create a
property to tell the usercontrol not to handle the event.

Oh well. I will create a simple C# app to see what I see there.

Thanks
LS
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top