Getting index of button clicked

zekeman

Well-known member
Joined
May 23, 2006
Messages
224
Programming Experience
10+
I've converted an app from VB6 to Express and I'm having trouble

getting the the array index of the dynamically created buttons when

the user clicks the button. In other words in VB6 in order to dynamically

create buttons on the fly you would first create an array of buttons

in the design view haveing the same name. Then in the source click event,

the index of the button that was clicked would be given in the index as

shown below is the old VB6 Subroutine:

VB.NET:
Private Sub DynButton_Click([COLOR=red]index[/COLOR] As Integer)
    'The [COLOR=red]index[/COLOR] provides the index of which array of button was clicked
    '...
 end Sub

----------------


The Express converter converted the code to
VB.NET:
[SIZE=2][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] DynButton_Click([/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] eventSender [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Object, [/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] eventArgs [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.EventArgs) [/SIZE][SIZE=2][COLOR=#0000ff]Handles[/COLOR][/SIZE][SIZE=2] DynButton.Click
[/SIZE]Dim [COLOR=red]index[/COLOR] As Short = DynButton.GetIndex(eventSender)
  'above has no warnings but errors when I set option strict on
  '...
end sub



So I can't build the code (error free) with option strict on and use the
statement:
Dim index As Short = DynButton.GetIndex(eventSender)

but I need the index and I want to use strick on

Thanks
 
Why do you need the array index? You got reference to the button in 'eventSender'. eventSender IS the button that was clicked.
 
The subroutine is going to take action based on which dynamic

button was clicked. Since button 1 could be 'cancel' or button 2 could

be 'submit'. Using an array of buttons, means that I have 1 to many

buttons I've created with the old VB6. 'Load' statement. Then when

the sub clicked is called ( for all buttons ) I need to figure out which

one of the dynamic buttons were clicked. I need to convert/get

eventSender into an integer that I can then use to address the

particular button the user clicked.

Since this is old VB stuff - using 'load' to add controls at run time.
its probably hard to relate to. Here is a link about creating runtime
controls - not that there is pertinant info - but just so you can see
what I mean - better explanation.
http://builder.com.com/5100-6228-5458636.html

I will be glad to answer any additional question qualifiers.
Thanks again
 
Oh, is it possible to add controls to form dynamically? I didn't know that. Just kidding. lol. Still don't understand why you need the index of the array - you got the reference to the control and that is what your after anyway, isn't it? Say, somehow someone gave you that index, what would you use it for? You would access the array by index to get the control. No need for that, you got the control, it is the 'eventSender'. Check the name of the sender in event handler, if a simple number is your control qualifier you could dynamically Name or Tag them in this manner, like 'button1' 'button2' etc.
 
ControlArrays don't exist in VB.NET as they did in VB6. If you have an array of buttons and you want to know the index of a particular button then you would use the oddly-named IndexOf method.
VB.NET:
Dim buttonIndex As Integer = Array.IndexOf(myButtonArray, myButton)
In your code myButton will be eventSender. Note that the consensus is that using the upgrade wizard is a bad idea. You end up with ugly code and you spend almost as much time fixing errors as you would have writing new code. It's generally considered preferable to just forget VB6 existed, decide what it is you want to achieve and find the best way to do that in VB.NET. If you start from VB6 and try to translate to VB.NET you do yourself a disservice because there is no direct translation in many cases and you end up wasting time trying to make VB.NET work like VB6 did and you end up with bad code as a result.
 
I gotta laugh! This is the funist thread I've read yet.

I can tell that I'm dealing with some smart people here - and that's what
I need.:) Thanks for your help!

I need the index of the button so I can get to the properties of the particualr button that was clicked.

by-the-way, now I finally understand what you mean when
when you say re-write the code -I couldn't see that before.

Now, Im doing a practice app conversion from VB6 to .Net so I can get a feel for the correct way to do them. I won't re-write this one
now, but will try on the next one.

JohnH said:
VB.NET:
No need for that, you got the control, it is the 'eventSender'

Yes, I agree but why can't I then say: eventsender.backcolor

Well I'll try this and get back to you on how well it works:

Dim clickedButton As Control = DirectCast(eventSender, Button)
'now the clickedButton followed by a '.' makes the VB2005 IDE
' give me all kinds of drop downs options such as the backcolor
' so now I can say clickedButton.backcolor
'...
 
Last edited:
You can't just use "eventSender.BackColor" because eventSender is type Object and Object has no BackColor property. Event handlers can handle events for any type of object so the standard is to pass the object that raised the event as a Object reference and then cast as required, as you're doing with DirectCast. That code is declaring a variable of type Control and assigning the eventSender to it, which you can do because the object that eventSender refers to IS a control. The Control class does have a BackColor property so you can set it through a reference of that type. If you know for a fact that this method will only handle events for Button objects then you should use the the Button type rather than Control:
VB.NET:
Dim clickedButton As Button = DirectCast(eventSender, Button)
This will work fine as long as only Buttons' events are handled by that method. If any other type of object is passed to the eventSender argument then it will crash. To add that extra little bit of safety you can also do this:
VB.NET:
Dim clickedButton As Button = TryCast(eventSender, Button)

If clickedButton IsNot Nothing Then
Where DirectCast will throw an exception if the object is not a Button, TryCast will simply retrun Nothing. If clickedButton is Nothing then it will what's inside the If block will not be executed. That way you do something only for Buttons but if you accidentally do pass some other type your app will handle it gracefully.
 
Looks good and is working and because your thoroughness
actually answered my next question.

In the following code I was trying to find out if the checkbox
had been checked but couldn't see the 'checked' property
in the IDE drop down.

But changing from 'Control' to RadioButton gave me the 'checked'
property that I needed.
VB.NET:
[SIZE=2][COLOR=#0000ff]Private[/COLOR][/SIZE][SIZE=2][COLOR=#0000ff]Sub[/COLOR][/SIZE][SIZE=2] DynOption_CheckedChanged([/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] eventSender [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.Object, [/SIZE][SIZE=2][COLOR=#0000ff]ByVal[/COLOR][/SIZE][SIZE=2] eventArgs [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] System.EventArgs) [/SIZE][SIZE=2][COLOR=#0000ff]Handles[/COLOR][/SIZE][SIZE=2] DynOption.CheckedChanged
[/SIZE][SIZE=2][COLOR=#0000ff] 'Dim[/COLOR][/SIZE][SIZE=2] clickedRadioButton [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] Control = [/SIZE][SIZE=2][COLOR=#0000ff]DirectCast[/COLOR][/SIZE][SIZE=2](eventSender,   RadioButton)' [COLOR=red]wrong way[/COLOR]
[/SIZE][SIZE=2][COLOR=#0000ff] Dim[/COLOR][/SIZE][SIZE=2] clickedRadioButton [/SIZE][SIZE=2][COLOR=#0000ff]As[/COLOR][/SIZE][SIZE=2] RadioButton = [/SIZE][SIZE=2][COLOR=#0000ff]TryCast[/COLOR][/SIZE][SIZE=2](eventSender, RadioButton)' [COLOR=red]correct way, now get the checked property[/COLOR][/SIZE]
  '..
  If clickedRadioButton IsNot Nothing Then
    if clickedRadioButton.checked = true then
      '...
    end if
  end if
end sub

Fantastic Thanks
 
One way to make that code a little neater is to remove the unnecessary nested If statements:
VB.NET:
If clickedRadioButton IsNot Nothing AndAlso clickedradioButton.Checked Then
Unlike And and Or, the AndAlso and OrElse operators use short-circuiting, which means if no subsequent expressions can change the result of the overall expression they are not evaluated. In this case if the first condition is False then no subsequent condition can make the overall expression True, so no more expressions are evaluated. That measn that no attempt is made to evaluate the Checked property so no exception will be thrown because it doesn't exists. If you were to use And instead of AndAlso then the second expression would be evaluated regardless and an exception would be thrown if the sender was not a RadioButton.
 
I need all the exception-'l help I can get since my first app built with

option strick, 0 error, 0 warnings, but failed to run on the first other

PC I loaded it on due to an exception error. But that's another thread

I guess. Seems like .Net throws more exceptions ?

Thanks for the lesson
 
it throws more exceptions? no.. only one for each error it encounters.. :)

Worried Passenger: "Captain, do ships of this size sink often?"
Captain: "No, only once"
 
Back
Top