Using AddHandler

R

Rick Palmer

I have an app I'm working on that will allow a user to run one of 5
reports. The report names are in a combobox on my form. I have a sub
defined for each report that has the exact same name as is displayed
in the combobox. I have one button on the form to start processing.
What I want to do is this: When the user selects the report they want
to run from the combobox, I want to dynamically bind the appropriate
sub to the button's click event. Since the sub names are the same as
the display names in the box, I'm wanting to do it like this:

Addhandler Button1.Click, combobox1.text

Unfortunately, that makes VB look for a sub called "combobox1.text",
instead of looking for the function named in combobox1.text. Anyone
know how to do what I'm trying to do????

-rp
 
H

Herfried K. Wagner [MVP]

Rick Palmer said:
the display names in the box, I'm wanting to do it like this:

Addhandler Button1.Click, combobox1.text

Add 'AddressOf' in front of the 'combobox1.text'.
 
K

Ken Tucker [MVP]

Hi,

1) Combobox1.text is a property of a combobox. You should not name a
function or a sub the same as a property of a control

2) Use address of in addhandler so the compilier knows where to find the
procedure
Addhandler Button1.Click, Addressof MyEventHandler

3) AddHandler only works with sub routines they do not work with functions.
They must accept the same arguments as the event is expecting.

Ken
---------------------
I have an app I'm working on that will allow a user to run one of 5
reports. The report names are in a combobox on my form. I have a sub
defined for each report that has the exact same name as is displayed
in the combobox. I have one button on the form to start processing.
What I want to do is this: When the user selects the report they want
to run from the combobox, I want to dynamically bind the appropriate
sub to the button's click event. Since the sub names are the same as
the display names in the box, I'm wanting to do it like this:

Addhandler Button1.Click, combobox1.text

Unfortunately, that makes VB look for a sub called "combobox1.text",
instead of looking for the function named in combobox1.text. Anyone
know how to do what I'm trying to do????

-rp
 
R

Rick Palmer

Like I said in my previous email, that would make VB look for a Sub
called "combobox1.text". But that's not the case. The case is the
name of the sub I want to call is IN combobox1.text....See?


-rp
 
R

Rick Palmer

Let me phrase it a different way....


There are three reports: Written_Premiun, Earned_Premium, and
Unearned_Premium.

These 3 report names are items in a combobox on my form.

The code for the form has a seperate sub corresponding to each of the
reports. The subs are named EXACTLY the same as their corresponding
items in the combobox, like so:

Public Sub Written_Premium(...
Public Sub Earned_Premium(...
Public Sub Unearned_Premium(..

I only have one button to start processing.

When the user selects their desired report from the combobox, I want
to bind the appropriate sub to the button.click event. Since I named
each Sub exactly as it's corresponding item in the combobox, it can be
said that the combobox contains the name of the sub we want to bind to
the button's click event.

So let's say I choose "Written_Premium from the combobox....

If my code is written like this:

AddHandler(Button1.Click, AddressOf combobox1.text)

Then VB will be looking for a sub named "combobox1.text", which
doesn't exist, instead of looking for

Does that clarify things any????
 
I

Imran Koradia

Instead of doing that, you could do something like this:

Public Class Form1
Inherits System.Windows.Forms.Form
' omiting designer code..
' one button - Button1
' one combobox - Combobox1

Enum ReportTypes
Report1
Report2
Report3
End Enum

Private arr As New ArrayList

Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
With arr
.Add(ReportTypes.Report1)
.Add(ReportTypes.Report2)
.Add(ReportTypes.Report3)
End With
ComboBox1.DataSource = arr
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Select Case ComboBox1.SelectedIndex
Case ReportTypes.Report1
' call Report1 procedure..
Case ReportTypes.Report2
' call Report2 procedure..
Case ReportTypes.Report3
' call Report3 procedure..
End Select
End Sub

End Class

hope that helps..
Imran.
 
R

Rick Palmer

Yes, but the way you've show below, if I added a new report, I would
have to add it:
1) to the Enum
2) to the Case Select Statement
3) to the With... statement that fills the arraylist
in addition to writing the new code....That leaves two chances for me
to forget to add it somewhere and make myself look like like a dumbass
when it goes into production. The way I'm trying, you would only have
to add an entry to the combobox and add the code.

I actually figured out how to do this without using AddHandler.
Instead of changing handler for the button.click event, I just use one
handler, ion which I use System.Type.InvokeMember to call the
subroutine named in the combobox.
 
I

Imran Koradia

Well - you can avoid (3) by doing something like:

For Each sReportType As String In [Enum].GetNames(ReportTypes)
arr.Add(sReportType)
Next sReportType

Also, IMHO, that's a bit more clean and also avoids the overhead that
reflection incurs. I wouldn't want to use reflection if I know the type and
method I need to execute. I would usually resort to Reflection only when I
really need to (late binding because of unknown types, etc). Just a
thought..

Imran.
 
J

Jay B. Harlow [MVP - Outlook]

Imran,
You can actually reduce that to

arr.AddRange([Enum].GetValues(GetType(ReportTypes)))

Although I think I would skip the ArrayList and simply add the values to the
Items collection of the ComboBox. Something like:

ComboBox1.Items.AddRange([Enum].GetValues(GetType(ReportTypes)))

Then in my Button_Click I would use the SelectedValue:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Select Case ComboBox1.SelectedItem
Case ReportTypes.Report1
MessageBox.Show("call Report1 procedure...")
Case ReportTypes.Report2
MessageBox.Show("call Report2 procedure...")
Case ReportTypes.Report3
MessageBox.Show("call Report3 procedure...")
Case Else
Throw New ArgumentOutOfRangeException("ReportType",
ComboBox1.SelectedItem, "Invalid Report Type in ComboBox1.")
End Select
End Sub

Private Sub MainForm_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles MyBase.Load
For Each item As ReportTypes In
[Enum].GetValues(GetType(ReportTypes))
ComboBox1.Items.Add(item)
Next
ComboBox1.SelectedItem = ReportTypes.Report1
End Sub

Note due to GetValues returns an array of Enum, and not Object, I had to use
a For Each.

Note: I am putting actual Enum values into the ComboBox, not the name of the
values, because the combo box will call Enum.ToString, the string name of
the enum will be displayed...

Hope this helps
Jay

Imran Koradia said:
Well - you can avoid (3) by doing something like:

For Each sReportType As String In [Enum].GetNames(ReportTypes)
arr.Add(sReportType)
Next sReportType

Also, IMHO, that's a bit more clean and also avoids the overhead that
reflection incurs. I wouldn't want to use reflection if I know the type
and
method I need to execute. I would usually resort to Reflection only when I
really need to (late binding because of unknown types, etc). Just a
thought..

Imran.

Rick Palmer said:
Yes, but the way you've show below, if I added a new report, I would
have to add it:
1) to the Enum
2) to the Case Select Statement
3) to the With... statement that fills the arraylist
in addition to writing the new code....That leaves two chances for me
to forget to add it somewhere and make myself look like like a dumbass
when it goes into production. The way I'm trying, you would only have
to add an entry to the combobox and add the code.

I actually figured out how to do this without using AddHandler.
Instead of changing handler for the button.click event, I just use one
handler, ion which I use System.Type.InvokeMember to call the
subroutine named in the combobox.
 
I

Imran Koradia

Right..thats even cleaner and more concise. Basically, not to go the
reflection way (InvokeMember) if you can avoid it (ofcourse with not a whole
lot more).

Thanks for the input, Jay.
Imran.

Jay B. Harlow said:
Imran,
You can actually reduce that to

arr.AddRange([Enum].GetValues(GetType(ReportTypes)))

Although I think I would skip the ArrayList and simply add the values to the
Items collection of the ComboBox. Something like:

ComboBox1.Items.AddRange([Enum].GetValues(GetType(ReportTypes)))

Then in my Button_Click I would use the SelectedValue:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Select Case ComboBox1.SelectedItem
Case ReportTypes.Report1
MessageBox.Show("call Report1 procedure...")
Case ReportTypes.Report2
MessageBox.Show("call Report2 procedure...")
Case ReportTypes.Report3
MessageBox.Show("call Report3 procedure...")
Case Else
Throw New ArgumentOutOfRangeException("ReportType",
ComboBox1.SelectedItem, "Invalid Report Type in ComboBox1.")
End Select
End Sub

Private Sub MainForm_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles MyBase.Load
For Each item As ReportTypes In
[Enum].GetValues(GetType(ReportTypes))
ComboBox1.Items.Add(item)
Next
ComboBox1.SelectedItem = ReportTypes.Report1
End Sub

Note due to GetValues returns an array of Enum, and not Object, I had to use
a For Each.

Note: I am putting actual Enum values into the ComboBox, not the name of the
values, because the combo box will call Enum.ToString, the string name of
the enum will be displayed...

Hope this helps
Jay

Imran Koradia said:
Well - you can avoid (3) by doing something like:

For Each sReportType As String In [Enum].GetNames(ReportTypes)
arr.Add(sReportType)
Next sReportType

Also, IMHO, that's a bit more clean and also avoids the overhead that
reflection incurs. I wouldn't want to use reflection if I know the type
and
method I need to execute. I would usually resort to Reflection only when I
really need to (late binding because of unknown types, etc). Just a
thought..

Imran.

Rick Palmer said:
Yes, but the way you've show below, if I added a new report, I would
have to add it:
1) to the Enum
2) to the Case Select Statement
3) to the With... statement that fills the arraylist
in addition to writing the new code....That leaves two chances for me
to forget to add it somewhere and make myself look like like a dumbass
when it goes into production. The way I'm trying, you would only have
to add an entry to the combobox and add the code.

I actually figured out how to do this without using AddHandler.
Instead of changing handler for the button.click event, I just use one
handler, ion which I use System.Type.InvokeMember to call the
subroutine named in the combobox.




On Wed, 6 Oct 2004 15:00:17 -0400, "Imran Koradia"

Instead of doing that, you could do something like this:

Public Class Form1
Inherits System.Windows.Forms.Form
' omiting designer code..
' one button - Button1
' one combobox - Combobox1

Enum ReportTypes
Report1
Report2
Report3
End Enum

Private arr As New ArrayList

Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
With arr
.Add(ReportTypes.Report1)
.Add(ReportTypes.Report2)
.Add(ReportTypes.Report3)
End With
ComboBox1.DataSource = arr
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Select Case ComboBox1.SelectedIndex
Case ReportTypes.Report1
' call Report1 procedure..
Case ReportTypes.Report2
' call Report2 procedure..
Case ReportTypes.Report3
' call Report3 procedure..
End Select
End Sub

End Class

hope that helps..
Imran.

I have an app I'm working on that will allow a user to run one of 5
reports. The report names are in a combobox on my form. I have a sub
defined for each report that has the exact same name as is displayed
in the combobox. I have one button on the form to start processing.
What I want to do is this: When the user selects the report they want
to run from the combobox, I want to dynamically bind the appropriate
sub to the button's click event. Since the sub names are the same as
the display names in the box, I'm wanting to do it like this:

Addhandler Button1.Click, combobox1.text

Unfortunately, that makes VB look for a sub called "combobox1.text",
instead of looking for the function named in combobox1.text. Anyone
know how to do what I'm trying to do????

-rp
 
C

Cor Ligthert

Jay,

You make it forever nicer and nicer, basic people like me choose for the way
Imran did.

With that not saying that your method is not nicer.

:)

Cor
 

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