Results 1 to 22 of 22

Thread: Identify a control from parameters passed to event handler?

  1. #1

    Thread Starter
    Frenzied Member
    Join Date
    May 2004
    Location
    Carlisle, PA
    Posts
    1,045

    Identify a control from parameters passed to event handler?

    Esteemed Forum Participants and Lurkers:

    I'm still playing with arrays of buttons, and the more I get into it the more I realize why VB.Net is so cheap. It certainly lacks a lot of features I have experienced in the past.

    It is nice that button click calls can field more than 1 button, but what use is it? I can field as many buttons as desired in a single call, but as far as I can tell, there is no intrinsic way of telling which button activated the call!

    Playing around with an array of 10 Radio Buttons I discovered (NEWBIE ALERT!) that "sender" merely indicates what kind of control initiated the event, and "e" merely states that this handler has gotten a system event! Whoopie doo! I want to know WHO initiated the event! Which of my 10 Radio Buttons am I dealing with? I would like to CASE the buttons, but I sure don't know how without a "who" parameter. LabWindows CVI very nicely passed the ID of the control to the event handler. VB.Net leaves me out on a limb looking for kludges. Is there some high-class function that returns all "checked" buttons from a collection? That would be neat (since there is only 1)!
    Code:
        Private Sub RadioButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RadioButton1.Click
            ' Which control is checked?
            MsgBox(sender.ToString)  ' Whoopie doo!  a Radio Button
            MsgBox(e.ToString)  ' Whoopie doo!  a System Event
        End Sub
    Am I missing something?

    I still need a GOOD book! Any recommendations?
    Blessings in abundance,
    All the Best,
    & ENJOY!

    Art . . . . Carlisle, PA . . USA

  2. #2
    Lively Member ayan's Avatar
    Join Date
    Jan 2004
    Posts
    112
    like this?
    VB Code:
    1. Public Sub radiobuttons_click(ByVal sender As Object, ByVal e As EventArgs) Handles RadioButton1.Click, _
    2.     RadioButton2.Click, RadioButton3.Click, RadioButton4.Click, RadioButton5.Click, RadioButton6.Click, _
    3.     RadioButton7.Click, RadioButton8.Click, RadioButton9.Click, RadioButton10.Click
    4.         MessageBox.Show("who am i? " & sender.name)
    5.     End Sub
    if not, sorry...

  3. #3
    Lively Member ayan's Avatar
    Join Date
    Jan 2004
    Posts
    112
    or this? i don't know. hope this helps...
    VB Code:
    1. Dim r(9) As RadioButton
    2.     Function idontknow()
    3.         Dim i As Integer
    4.         Dim y As Integer = 22
    5.         For i = 0 To r.Length - 1
    6.             r(i) = New RadioButton()
    7.             r(i).Name = "radio button " & i
    8.             r(i).Text = r(i).Name
    9.             r(i).Location = New Point(20, y)
    10.  
    11.             y += 22
    12.             Me.Controls.Add(r(i))
    13.  
    14.             AddHandler r(i).Click, AddressOf xidontknow
    15.         Next
    16.     End Function
    17.  
    18.     Public Sub xidontknow(ByVal sender As Object, ByVal e As EventArgs)
    19.         MessageBox.Show(sender.name)
    20.     End Sub
    and oh, please don't say VB.Net is so cheap...
    Last edited by ayan; May 27th, 2004 at 09:36 PM.

  4. #4
    Your Ad Here! Edneeis's Avatar
    Join Date
    Feb 2000
    Location
    Moreno Valley, CA (SoCal)
    Posts
    7,339
    As ayan points out its not that '"sender" merely indicates what kind of control initiated the event' sender IS the control that raised the event.

    It is wise to cast the sender to its proper type if you know what it is. Then you can access its members correctly.
    VB Code:
    1. Private Sub RadioButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RadioButton1.Click
    2.           'cast it
    3.           Dim rb As RadioButton=Ctype(sender,RadioButton)
    4.           'use it
    5.           Msgbox(rb.Text)
    6.     End Sub

  5. #5

    Thread Starter
    Frenzied Member
    Join Date
    May 2004
    Location
    Carlisle, PA
    Posts
    1,045
    Thanks to you all for your gracious help ... I still need a recommendation for a GOOD book!

    Your comments were ALL excellent and I'm starting to pick up speed in this stuff now.

    I just didn't intuitively make the connection that "sender" was a handle to the actual radio button! All I could find in the Help pages under System.Object was "ToString" which I thought would give me useful info about the identity of "sender".

    Thanks to Edneeis for REALLY clarifying the point ... now I just need to dig deeper into the casting concepts. I was surprised that "sender.checked" gets through the editor unscathed and operable (returns "True"), even though the "checked" is not recognized as a property of sender by the editor (it stays "checked" instead of getting corrected to the proper "Checked"). I'm presuming if I cast "sender" to RadioButton as Edneeis recommends that the editor will miraculously recognize all of the RadioButton properties of sender. I previously had problems getting "Checked" recognized at all when I indirectly referenced a RadioButton as "Control", but it worked (of course) when I referenced it as a RadioButton.

    My apologies for letting my frustration show through in my posting, and thank you all for your gracious assistance.

    I still need a recommendation for a GOOD book!
    Blessings in abundance,
    All the Best,
    & ENJOY!

    Art . . . . Carlisle, PA . . USA

  6. #6
    Frenzied Member
    Join Date
    Feb 2003
    Location
    Argentina
    Posts
    1,950
    Why would you need to cast sender to a radiobutton in a radiobutton click event? Wouldn't sender always be a radiobutton? Or does it come across as a generic object? Just curious.

  7. #7

    Thread Starter
    Frenzied Member
    Join Date
    May 2004
    Location
    Carlisle, PA
    Posts
    1,045
    Savelinus ...

    The system knows that sender is a RadioButton AT RUN TIME! If you cast sender to RadioButton while building the code, I think that all of the RadioButton properties for sender will be recognized.

    While you are editing, without the cast, the ONLY 'automatic' property that you have for sender in the popup menu is "sender.GetType()". My guess is that after you cast sender to RadioButton, when you type "sender." the entire resources for RadioButton will appear in the popup, including "Name", "Checked", and "TabIndex".

    My handler now fields all 10 buttons! The Button function names (departments) are loaded in a Global array by TabIndex, and I can now process everything just by reading the TabIndex for sender!

    Set the TabIndex of each button as 0 through N

    In a module ...
    Code:
    Public g_Name as String = _
    {"Dept1","Dept2", ... ,"DeptN"}
    
    'The Handler:
            If sender.Checked Then
                'TEST TEST TEST TEST
                MsgBox("This is the " + g_Name(sender.TabIndex) + " Department")
                'END TEST
            End If
    It really works GREAT!
    Blessings in abundance,
    All the Best,
    & ENJOY!

    Art . . . . Carlisle, PA . . USA

  8. #8
    Frenzied Member
    Join Date
    Feb 2003
    Location
    Argentina
    Posts
    1,950
    Hmm, so the cast is for intellisense when coding, then?
    Anyway, if you're going to use tabindex, you might want to look at the tag property instead. If you use tabindex, you'll have to be sure it never changes.

  9. #9
    yay gay PT Exorcist's Avatar
    Join Date
    Apr 2002
    Location
    . . . my reason of shame
    Posts
    2,729
    Originally posted by salvelinus
    Hmm, so the cast is for intellisense when coding, then?
    Anyway, if you're going to use tabindex, you might want to look at the tag property instead. If you use tabindex, you'll have to be sure it never changes.
    Hmm, actually the casting is to make sure you are working with the correct data type and can access its properties/data members, and a consequence of that is having the IDE showing you the class' things
    \m/\m/

  10. #10
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687
    salvelinus - I've been having success reading the book Mastering Visual Basic .NET by Evangelos Petroutsos (Sybex Publishing).

    It's a very thick book, and taks some getting used to, but so far it's been very helpful to me.

    TG
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  11. #11

    Thread Starter
    Frenzied Member
    Join Date
    May 2004
    Location
    Carlisle, PA
    Posts
    1,045
    Salvelinus ...

    I don't think VB mungs with the TabIndex property of a control after you assign it ... if you set them on the Form as you design it I think they are safe. It IS possible to set more than 1 control with the same index though! I just created my panel and then did a "View > Tab Order" and made sure everything was in order.


    PT Exorcist ...

    So far I haven't found any properties of the RadioButton that weren't recognized at run time without casting "sender". So at run time, "sender" seems to have all the properties (of the RadioButton that generated the event) by default, so casting doesn't seem to be absolutely necessary. It would be hard to cast "sender" if you were processing more than 1 type of control, but I can't imagine wanting to handle different types of controls through a common handler. Casting does make the code absolutely clear, and it is easier to write the code!


    Techgnome ...

    Thanks for the book comments.
    Blessings in abundance,
    All the Best,
    & ENJOY!

    Art . . . . Carlisle, PA . . USA

  12. #12
    Frenzied Member
    Join Date
    Feb 2003
    Location
    Argentina
    Posts
    1,950
    Originally posted by PT Exorcist
    Hmm, actually the casting is to make sure you are working with the correct data type and can access its properties/data members, and a consequence of that is having the IDE showing you the class' things
    Well, either a radio button is being passed in as sender, and wouldn't need a cast, or is passed in as an object, so needs a cast to access its members and properties. In a click event I don't see why you'd need to check for the correct data type in the first case, unless some other sender is handling the click event. The second case, sure.
    Originally posted by Webtest
    I don't think VB mungs with the TabIndex property of a control after you assign it ... if you set them on the Form as you design it I think they are safe.
    It won't change them if you delete something? Didn't know that.
    Originally posted by techgnome
    I've been having success reading the book Mastering Visual Basic .NET by Evangelos Petroutsos (Sybex Publishing).

    It's a very thick book, and taks some getting used to, but so far it's been very helpful to me.
    I've got that one, it's pretty good. Also use Beginning VB.Net, 2nd ed., and Murach's VB.Net database programming .
    I know VB 6, self teaching VB.Net, as well as VBA, php, MySql, FilePro (an old DOS db) at the same time. Sometimes I get 'em mixed up

  13. #13
    yay gay PT Exorcist's Avatar
    Join Date
    Apr 2002
    Location
    . . . my reason of shame
    Posts
    2,729
    Well, in VB.NET using sender.<some radiobutton property> will work because VB.NET allows late binding. But in C# for example you can only use methods/properties from sender's type (object), if you want to use radiobutton's one you will have to do casting first.
    In C# you will have to use casting if you want to use sender as an RadioButton. Vb.Net will allow you to do for example sender.LOL(), and even compile without raising any error.
    Now run the app..Wow! An error! That's the bad part about late binding - the compiler CAN'T know if you are trying to access something that doesn't exist or not.

    And if you are using a big loop that is resource intensive it will have to each time check what kind of object it is before calling the method/property you want, making your application lots slower.
    Last edited by PT Exorcist; May 28th, 2004 at 03:16 PM.
    \m/\m/

  14. #14
    PowerPoster techgnome's Avatar
    Join Date
    May 2002
    Posts
    34,687
    Originally posted by PT Exorcist
    Well, in VB.NET using sender.<some radiobutton property> will work because VB.NET allows late binding. But in C# for example you can only use methods/properties from sender's type (object), if you want to use radiobutton's one you will have to do casting first.
    In C# you will have to use casting if you want to use sender as an RadioButton. Vb.Net will allow you to do for example sender.LOL(), and even compile without raising any error.
    Now run the app..Wow! An error! That's the bad part about late binding - the compiler CAN'T know if you are doing **** or not and if you are using a big loop that is resource intensive it will have to each time check what kind of object it is before calling the method/property you want, making your application slower
    Piggy-backing on what PT said, VB.NET will allow you to late bind as long as OPTION STRICT is off (which it is by default). If you turn OPTION STRICT on, you MUST cast it before accessing the sender's properties.


    TG
    * I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
    * I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
    * How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
    * How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *

  15. #15
    Your Ad Here! Edneeis's Avatar
    Join Date
    Feb 2000
    Location
    Moreno Valley, CA (SoCal)
    Posts
    7,339
    Yes VB.NET with Option Strict on has the same rules as C#.

    The casting issue has to be with inheritance, you see the sender can be and is (you assume) in this case a RadioButton but it is also an Object. All objects derive or inherit from the base type Object. So then you have a situation where all poodles are dogs but not all dogs are poodles. All RadioButtons are objects but not all objects are RadioButtons. Anything can be passed as the sender since it takes the type Object. RadioButton gets passed because it is raising the event. Sender is always (almost) the object that raised or caused the event to fire. Since you only have one type of control handling that event then you are pretty sure that sender will be a RadioButton. This is not always safe as you could just call the method in code: RadioButton1_Click(Me,Nothing) and pass something else as the sender in which cause you'd get an error. So really you should check the type before casting.

    Casting converts a type to another type, so long as both types are in the same inheritance chain. In other words since RadioButton inherits from Object you can cast object to RadioButton. RadioButton also inherits from Control so does ListBox. Never the less since RadioButton doesn't inherit from ListBox if listbox got passed to your click event as type Object it could not be cast to RadioButton but it could be cast to Control. I hope that makes sense.

    Casting allows the compiler to check for errors at designtime and should always be used otherwise as PT mentioned you get funky stuff at runtime.

    Also TabIndexes are relative to their container. So when you see that multiple controls have the same TabIndex its because they are in different containers. This is shown in the TabOrder view by something like this: 2.1, 2.2, 3.1 with the Containers TabIndex followed by the control's tabindex.

  16. #16
    Frenzied Member
    Join Date
    Feb 2003
    Location
    Argentina
    Posts
    1,950
    Thanks Edneiss, that's pretty much what I thought originally, although you explained it much better. So although you (normally) wouldn't have to cast, it's safer to do so, and may be required in some cases.
    I still don't like using tabindexes to check most controls (tabcontrol may be an exception). I know it'll work most of the time, but I wouldn't have faith in it. I've worked on modifying 100k+ lines of code spread across multiple files (with no commenting or documentation anywhere) in Delphi, a kind of VB in Pascal, and it's really hard. You can make your changes and the modification will work right, but it screws up something else. So you have to test (or the customer does!) the whole app each time. Then when it doesn't, you pretty much have to step through hundreds of lines of code to figure out where the problem is. Fix that, and you're faced with the same problem. There was one sub that dozens of other subs called, and it did different stuff for them all. So any change, which almost had to use that sub, affected everything else. A huge pain & flaw.
    I know that's a function of the original software design, or lack of it, but most companies aren't going to redesign a whole system if they're still making money off of it.
    I know none of us here would do that
    I'm a big fan of short, simple subs/functions. A rule of thumb I use is that if the sub won't fit on a screen, consider breaking it up. Long subs that do a lot may be a bit faster than making a bunch of calls to other subs, but the benefits aren't worth it But we know that, right? At least that's my design strategy.

  17. #17
    Your Ad Here! Edneeis's Avatar
    Join Date
    Feb 2000
    Location
    Moreno Valley, CA (SoCal)
    Posts
    7,339
    "although you (normally) wouldn't have to cast, it's safer to do so"

    Actually you should always cast. Even if you don't then the compiler will still have to at runtime which on top of possible errors will be a performance hit because it will have to figure out what to cast it to at that time. I mean will your code work without casting - sometimes, but that doesn't mean you shouldn't do it.

    Of course this is just my personal opinion.

  18. #18
    Frenzied Member
    Join Date
    Feb 2003
    Location
    Argentina
    Posts
    1,950
    Well if the compiler does so at runtime anyway, does the explicit cast just duplicate it?
    One thing I'd like to see in the documentation for all languages is the order in which events are called.
    Edneiss, you ought to write a texbook. You explain things to us doofuses very well.

  19. #19
    Your Ad Here! Edneeis's Avatar
    Join Date
    Feb 2000
    Location
    Moreno Valley, CA (SoCal)
    Posts
    7,339
    No it doesn't duplicate it because if you cast it then the properties will match the type.

    It goes like this:

    The compiler reaches this point: sender.Name and says huh? sender is of type object and object does not have a name property so now I have to figure out what the hell this programmer meant by this line of code. Then it tries to go through the inheritance chain of that type for something that has a Name property. If it finds one it uses it otherwise it throws an exception. Then it says damn that was a lot of work I think I'll knock off for a while and go get a beer.

    Now with casting it reaches this point: DirectCast(sender,RadioButton).Name and it says oh I need to convert this to a RadioButton and then continue executing the line of code. Then it checks and says hey this object can convert to RadioButton. That was easy now the property Name matches to the type RadioButton and everyone is happy. Then it says wow that was easy I'm ready for more, bring it on!

    Of course I may be paraphrasing some of that but you get the idea.

    Here is a more codewise example. Using the following code:
    VB Code:
    1. Private Sub btnLateBinding_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLateBinding.Click
    2.         'late binding
    3.         MsgBox(sender.text)
    4.     End Sub
    5.  
    6.     Private Sub btnStrongTyped_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStrongTyped.Click
    7.         'strong typing or early binding
    8.         MsgBox(DirectCast(sender, Button).Text)
    9.     End Sub

    This is what Reflector decompiles it to:
    VB Code:
    1. Private Sub btnLateBinding_Click(ByVal sender As Object, ByVal e As EventArgs)
    2. Begin Sub
    3.  Interaction.MsgBox(RuntimeHelpers.GetObjectValue(LateBinding.LateGet(sender, Nothing, "text", New Object((0) - 1) {}, Nothing, Nothing)), 0, Nothing)
    4.  
    5. End Sub
    6.  
    7. Private Sub btnStrongTyped_Click(ByVal sender As Object, ByVal e As EventArgs)
    8. Begin Sub
    9.  Interaction.MsgBox(CType(sender,Button).Text, 0, Nothing)
    10.  
    11. End Sub

    And this is the IL for the different ways:
    VB Code:
    1. Private Sub btnLateBinding_Click(ByVal sender As Object, ByVal e As EventArgs)
    2.  
    3. .maxstack 8
    4. L_0000: nop
    5. L_0001: ldarg.1
    6. [b]L_0002: ldnull
    7. L_0003: ldstr "text"
    8. L_0008: ldc.i4.0
    9. L_0009: newarr Object
    10. L_000e: ldnull
    11. L_000f: ldnull
    12. L_0010: call LateBinding.LateGet
    13. L_0015: call RuntimeHelpers.GetObjectValue[/b]
    14. L_001a: ldc.i4.0
    15. L_001b: ldnull
    16. L_001c: call Interaction.MsgBox
    17. L_0021: pop
    18. L_0022: nop
    19. L_0023: ret
    20.  
    21. Private Sub btnStrongTyped_Click(ByVal sender As Object, ByVal e As EventArgs)
    22.  
    23. .maxstack 8
    24. L_0000: nop
    25. L_0001: ldarg.1
    26. [b]L_0002: castclass Button
    27. L_0007: callvirt Control.get_Text[/b]
    28. L_000c: ldc.i4.0
    29. L_000d: ldnull
    30. L_000e: call Interaction.MsgBox
    31. L_0013: pop
    32. L_0014: nop
    33. L_0015: ret
    Last edited by Edneeis; May 29th, 2004 at 03:26 PM.

  20. #20
    Frenzied Member
    Join Date
    Feb 2003
    Location
    Argentina
    Posts
    1,950
    Edneiss rules, man. I'm not a complete dolt, I've learned to various degrees VB6, C++, Java, Perl, VBA, VB.Net,Delphi, perl, php, and he can cut through the crap and show what's what.

  21. #21

    Thread Starter
    Frenzied Member
    Join Date
    May 2004
    Location
    Carlisle, PA
    Posts
    1,045
    Edneeis ... Savelinus ...

    Wow! All due respects to Edneeis ... on 5/28 he stated "when you see that multiple controls have the same TabIndex it's because they are in different containers". In VB.Net multiple controls in the SAME container may be assigned (by the designer) the SAME TabIndex. I saw a reference that said if this is the case, the actual tab order is resolved by the Z order (?) (relative position?).

    Savelinus ... deleting a control does NOT affect the TabIndex of other controls in the container. I tested this with a panel of 5 Radio Buttons, originally with a tab order sequence of 0 - 4. I changed the 4th control to a TabIndex of 2, and deleted the 2nd control. I ended up at Run Time with the following:

    RadioButton1 TabIndex = 0
    RadioButton3 TabIndex = 2
    RadioButton4 TabIndex = 2
    RadioButton5 TabIndex = 4

    Thanks again for everybody's help.
    Blessings in abundance,
    All the Best,
    & ENJOY!

    Art . . . . Carlisle, PA . . USA

  22. #22
    Your Ad Here! Edneeis's Avatar
    Join Date
    Feb 2000
    Location
    Moreno Valley, CA (SoCal)
    Posts
    7,339
    Originally posted by Webtest
    Wow! All due respects to Edneeis ... on 5/28 he stated "when you see that multiple controls have the same TabIndex it's because they are in different containers". In VB.Net multiple controls in the SAME container may be assigned (by the designer) the SAME TabIndex. I saw a reference that said if this is the case, the actual tab order is resolved by the Z order (?) (relative position?).
    Thats good to know. Thanks.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width