Event for Dynamically Created Controls

Hi All,

i have a form which creates the controls according to the no of records present in dataset 

and then these are binded to the certain row of the table of the dataset and my code for this is 

Sub createcontrols()

        Dim newtextbox As TextBox
        Dim newbutton As Button
        Dim x As Integer
        Dim k As Integer = 64

        For x = 0 To Me.Dsdespatchall1.END_USERS_ORDER_SALES_SUMMARY.Rows.Count - 1
            newtextbox = New TextBox
            newbutton = New Button
            newtextbox.Size = New System.Drawing.Size(135, 20)
            newbutton.Size = New System.Drawing.Size(40, 20)
            newbutton.Text = "GO"
            newtextbox.Location = New System.Drawing.Point(280, k)
            newbutton.Location = New System.Drawing.Point(440, k)
            newbutton.FlatStyle = FlatStyle.System
            newtextbox.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.Dsdespatchall1.END_USERS_ORDER_SALES_SUMMARY.Rows(x), "eu_order_status"))
            Me.Controls.Add(newtextbox)
            Me.Controls.Add(newbutton)
            k += 30
        Next x

    End Sub

now i want that when i press to a button created in a particulat iteration along with textbox it should perform a certain task according to the value of that textbox 

Best Regards

Ali Shah


Answer this question

Event for Dynamically Created Controls

  • Mark Blomsma

    Rkim..  dude that scares me ...  

    eeeck :) heheh sorry ...  I know thats its correct.. but scars me. :)

    if you store the key id in the button.tag or the panel.tag there would be no need to make the tag = to newtextbox :)

    because the text data is bound to the dataset. :) you know the key or Row(x) so you just would do a look up. :)

    if its Row(x) then answer would be

    itemfield = dataset1.table1.row(x).item("itemfield")

    if you have the key then you would have to do a dataview
    dim dv as new dataview
    dv.table = dataset1.table1
    dv.rowfilter = "primarykey = " & key 
    if dv.count > 0 then
    itemfielddv(0).item("itemfield")
    else
    msgbox "error"
    end if

    that would be in true dataset thinking :)

  • Rj_murray

    thanx rkimble and freibuis 

    it is working now having  cleared all my concepts about that and i am really enjoying your compay and discussion now. it is a fun for me 

    great i will be there with new thread soon 

    again thanx a lot lot and lot

    best ragards 
    Ali Shah

  • TokenWorks

    hi Rkimble,
    great i have picked the point i can access the properties of the button by this way. But still the problem is that i want to access the properties of the textbox created along that butoon. Pl tell me how can i do this 

    regards 

    Ali Shah

  • rax_uk

    Freibuis,

    Your code only allows access to the datarow that both the button and textbox are bound to; it does not give access to the textbox object the button is associated with via the datarow.  Now true, you could loop back through the controls so that if button3 is clicked you can find the textbox with the same tag info... but that is a lot of work for nothing.

    Simply storing a reference to the appropriate textbox object in the tag of the button is far easier.  You can now access the associated textbox without trying to pick it out of all the other textboxes on the form.

    Also, as an aside to your code, you don't need to instanciate a DataView just to search a table for a indexed value.  You can use the DefaultView on the table, or if it is a strongly typed table (that is, one in a design time generated dataset), it has a FindByID method.

  • Goran Glisic

    ali I answerd it in your other post..   
    http://www.windowsforms.com/Forums/ShowPost.aspx tabIndex=1&tabId=41&PostID=24536

  • John J. Adams

    Hi freibuis,

    I like seeing all the different ways things can be acomplished too.  =)

    Since the Tag property takes an Object as its value, either of our methods can only store one piece of info there (unless we use an array, as you noted).  In my example I store a TextBox object, in your's you store an Integer (keyid).

    In your example, the common info between the Button and TextBox is the Tag value (keyid).  A function to get the TextBox by the associated Button's Tag value would be:


        Private Function GetButtonsTextBox(ByVal btn As Button) As TextBox

            Dim enm As IEnumerator = btn.Parent.Controls.GetEnumerator

            While enm.MoveNext

                If enm.Current.GetType Is GetType(TextBox) Then

                    If CType(enm.Current, TextBox).Tag = btn.Tag Then

                        Return CType(enm.Current, TextBox)

                    End If

                End If

            End While

        End Function


    That will let you pass in the button that was clicked [GetButtonsTextBox(CType(sender, Button))] and get back the associated TextBox.  You could support multiple associations by adding an ArrayList to the function and changing the function itself to return an array of TextBoxes.  You would just add to the arraylist instead of returning and return an array of textboxes from the arraylist when the loop finished.

    On the FindByID thing...  I haven't had issues with it myself, but that may have to do with database design...  Most tables I build are pretty straight-forward, with one indexed field that is seeded and set as primary key.

    Anyway, it is fun to learn and share!  What's the book you found that you like   A good ADO read is hard to find!

  • Philip Borchert

    Well, if you changed the object stored in the Tag property to the control array instead of a single textbox, you also need to modify DoStuff to convert the type of Tag to a control array instead of a textbox.  Something like:


    'Get associated TextBox 1
    Dim tb1 As TextBox = CType(CType(sender, button).Tag, Object())(0)

    'Get associated TextBox 2
    Dim tb2 As TextBox = CType(CType(sender, button).Tag, Object())(1)


    Whatever object type you store in the Tag property of the Button is the object type you must convert to in your DoStuff code.

    Make sense

  • Hicham_IT

    <b>Edited by KraGiE: Please use < code> to make your code look presentable when you copy/paste</b>

    hi rkimble back again in this thread 

    but i really need now the multiple textboxes association support and in the function above you have described that the multiple support is possible but again i am confused how to use it in my code 

    which is 

        Dim newbutton As Button
        Dim newtextbox As TextBox
        Dim newtextbox1 As TextBox
        Dim newpanel As Panel

    these are class level variables

    and in my subroutine 

     Sub createcontrols()

            Dim x As Integer
            Dim k As Integer = 48

            For x = 0 To Me.dv.Count - 1

                'textbox
                newtextbox = New TextBox
                With newtextbox
                    .Size = New System.Drawing.Size(75, 20)
                    .Location = New System.Drawing.Point(16, 16)
                    .DataBindings.Add(New System.Windows.Forms.Binding("Text", dv(x), "eu_order_status"))
                    .BackColor = System.Drawing.Color.LemonChiffon
                     End With

    newtextbox1 = New TextBox
                With newtextbox1
                    .Size = New System.Drawing.Size(50, 20)
                    .Location = New System.Drawing.Point(16, 16)
                    .DataBindings.Add(New System.Windows.Forms.Binding("Text", dv(x), "eu_order_id"))
                    .BackColor = System.Drawing.Color.LemonChiffon
                     End With

                'newbutton
                newbutton= New Button
                With newbutton
                    .Size = New System.Drawing.Size(60, 20)
                    .Text = "Despatch"
                    .Location = New System.Drawing.Point(845, 6)
                    .FlatStyle = FlatStyle.System
                    .Tag = dv(x).Item("eu_order_id")
                End With

                newbutton.Tag = newtextbox

     'panel
                newpanel = New Panel
                With newpanel
                    .Tag = dv(x).Item("eu_order_id")
                    .Size = New System.Drawing.Size(900, 28)
                    .Location = New System.Drawing.Point(16, k)
                    .BackColor = System.Drawing.Color.LemonChiffon
                End With

                AddHandler llabel.Click, AddressOf dostuff

    newpanel.Controls.Add(newtextbox)
    newpanel.Controls.Add(newtextbox1)
    newpanel.Controls.Add(newbutton)
     Me.Controls.Add(newpanel)
                k += 32
            Next
        End Sub

    and then in my dostuff

    Private Sub dostuff(ByVal sender As System.Object, ByVal e As System.EventArgs)
            GetllabelTextBox(llabel)
            If newtextbox.Text = "Despatch Stock No CC" Then
                Dim a As New despatchedorder
                a.ShowDialog()
            Else
                Dim a As New Despatchcc
                a.ShowDialog()
            End If
        End Sub

    it is working very nicely but i really need to get the newtextbox1 property as well along with newtextbox 
    pl describe how can i use your function to add arrayof textboxes in my code 

    best regards 

    Ali Shah

  • DiscordianWarrior

    As freibuis noted, there is a "Tag" property on the Button object that can take any other object as it's value.  The simplest thing would probably be to set:

    newbutton.Tag = newtextbox

    Now your event handler can refer to:

    CType(CType(sender, Button).Tag, TextBox)

    to access the appropriate TextBox object.

  • Guillermo Leal-Collazo

    sorry Rkimble it is actually newbutton not the llabel you mentioned

    and now the problem is that in my dostuff my code is 

    newtextbox = CType(CType(sender, button).Tag, TextBox)
                 MsgBox(newtextbox.Text)
            MsgBox(newtextbox1.Text)

    but it gives the error message 

    specified cast is not valid

    and if in my code i write 


    mycontrols(0) = CType(CType(sender, button).Tag, TextBox)
    mycontrols(1)=CType(CType(sender, button).Tag, TextBox)

    gives the same error message 

    specified cast is not valid

    seeking help again

    Ali Shah

  • Wassimn

    First, you need to write the subroutine that contains the code you want to run when the button is clicked (for this example we'll use "DoButtonClick").  Then, in your loop, you will add a handle to this sub for the desired event on the control:

    AddHandler newbutton.Click, AddressOf DoButtonClick

    The only trick is that the control needs to be class level.  So your code should look like:



    Dim newbutton As Button 

    Sub createcontrols() 

    Dim newtextbox As TextBox 
    Dim x As Integer 
    Dim k As Integer = 64 

    For x = 0 To Me.Dsdespatchall1.END_USERS_ORDER_SALES_SUMMARY.Rows.Count - 1 
    newtextbox = New TextBox 
    newbutton = New Button 
    newtextbox.Size = New System.Drawing.Size(135, 20) 
    newbutton.Size = New System.Drawing.Size(40, 20) 
    newbutton.Text = "GO" 
    newtextbox.Location = New System.Drawing.Point(280, k) 
    newbutton.Location = New System.Drawing.Point(440, k) 
    newbutton.FlatStyle = FlatStyle.System 

    AddHandler newbutton.Click, AddressOf DoButtonClick

    newtextbox.DataBindings.Add(New System.Windows.Forms.Binding("Text", Me.Dsdespatchall1.END_USERS_ORDER_SALES_SUMMARY.Rows(x), "eu_order_status")) 
    Me.Controls.Add(newtextbox) 
    Me.Controls.Add(newbutton) 
    k += 30 
    Next x 

    End Sub 




    Then your DoButtonClick sub would look something like:


    Private Sub DoButtonClick(ByVal sender As System.Object, ByVal e As System.EventArgs)

    'Code to do work....

    End Sub



    The sub looks like a normal Button.Click event handler, but without the "Handles" clause (you could also hook an existing Button.Click event - having a handles clause won't prevent this from working).  In the sub you'll need to do something like:

    CType(sender, Button) to access the properties of the actual button that called the subroutine.

    Make sense

  • Othmane Rahmouni-MSFT

    Hi everybody. I'm interested with your discussions about this databinding thing as I'm looking  use it right now. In my case, I already build 8 button and want them to be a control array. I want to load the first field of "mkan" table in "makan.xml" file into the array of button, one each. And when I press a button, the respected second field will be loaded in textbox2 and the text in textbox1 will be the same as the button pressed. The first field named "food" and the second field named "price". Here is my code:


    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            'remove bindings and dispose panels 
            Dim y As Integer
            For y = 0 To Me.Controls.Count - 1 Step -1
                Me.Controls.Item(y).Controls.Item(0).DataBindings.Clear()
                Me.Controls.Item(y).Dispose()
            Next

            Dim dv As New DataView
            Dim dataset1 As New DataSet

            'Setup controls 
            dataset1.ReadXml("..\makan.xml")
            dv.Table = dataset1.Tables(0)
            Dim x As Integer
            Dim btnItem(8) As Button

            For x = 0 To dv.Count - 1
                btnItem(x).DataBindings.Add(New System.Windows.Forms.Binding("Text", dv(x), "food"))    ' * 
                x += 1
            Next x
        End Sub

        Private Function GetButtonsTextBox(ByVal btn As Button) As TextBox
            Dim enm As IEnumerator = btn.Parent.Controls.GetEnumerator
            While enm.MoveNext
                If enm.Current.GetType Is GetType(TextBox) Then
                    If CType(enm.Current, TextBox).Tag = btn.Tag Then
                        Return CType(enm.Current, TextBox)
                    End If
                End If
            End While
        End Function

    I'm new in programming vb.net. I don't know what's wrong with my code but the line marked with * causing nullreference exeption where object ref not set to an instance of an object and I don't know how what is the function of "Function GetButtonsTexbox" and how to use it. Please help me..

    Thank you in advance.

    CtKat

  • adrianol

    kimby :)

    the button is not bound it only hold as a refrence to the keyid or row(x)

    you are right about no access to the the textbox object. but 90% of the cases you only need the value in the text field.. other wise I would hace said what you said..

    for x = 0 to newbutton.parent.controls.count -1
    if  newbutton.parent.controls.item(x).name = "controlname" then  'or use a case for mutlpe conotrols
    'do stuff
    end if
    next

    I would have to agreee your way makes sense., but it would only allow one control bound to it unless you bound it as an array control.
    dim newtextbox(n) as textbox = new textbox

    I surpose you could do it that way.

    with the dataview comment..   from past experiences using the FindbyID throws me conversion errors from time to time.  Datarow type cannont convert to Interger type

    dim rowx as interger = dataset1.table1.findbyid(keyid)
    this throw out the error..  so to get around that I a dataview look up..  I know that would slow it down but removed that error.

    the ado.net book I am reading right now (great read) says that dataset1.table1.findbyid(keyid) returns a datarow. but it does not tell me what the index of the table its from...  well I like and learn :)
     





    thanks dude I always like having a diffrent way of doing somthing :) makes the mind open to other possiblitys

  • Rockfan

    Ali,

    I would suggest that in your CreateControls loop you create a new control array that is the size of the total number of controls that you want to associate with the button (right now, that looks like two textboxes):


    Sub createcontrols()

    Dim x As Integer
    Dim k As Integer = 48

            For x = 0 To Me.dv.Count - 1

    'CREATE THE CONTROL ARRAY TO HOLD OUR ASSOCIATED CONTROLS
    Dim myControls(1) As Control

                'textbox

                newtextbox = New TextBox

                With newtextbox

                    .Size = New System.Drawing.Size(75, 20)

                    .Location = New System.Drawing.Point(16, 16)

                    .DataBindings.Add(New System.Windows.Forms.Binding("Text", dv(x), "eu_order_status"))

                    .BackColor = System.Drawing.Color.LemonChiffon

                     End With


    'SET THE REFERENCE TO THE FIRST ASSOCIATED TEXTBOX
    myControls(0) = newtextbox


    newtextbox1 = New TextBox

                With newtextbox1

                    .Size = New System.Drawing.Size(50, 20)

                    .Location = New System.Drawing.Point(16, 16)

                    .DataBindings.Add(New System.Windows.Forms.Binding("Text", dv(x), "eu_order_id"))

                    .BackColor = System.Drawing.Color.LemonChiffon

                     End With

    'SET THE REFERENCE TO THE SECOND ASSOCIATED TEXTBOX
    myControls(1) = newtextbox

                'newbutton

                newbutton= New Button

                With newbutton

                    .Size = New System.Drawing.Size(60, 20)

                    .Text = "Despatch"

                    .Location = New System.Drawing.Point(845, 6)

                    .FlatStyle = FlatStyle.System

    'THIS ISNT NEEDED AS YOU ARE ABOUT TO CHANGE IT IN THE NEXT LINE
                    .Tag = dv(x).Item("eu_order_id")

                End With


    'INSTEAD OF USING ONE TEXTBOX, WE WILL USE OUR CONTROL ARRAY
                'newbutton.Tag = newtextbox

    newbutton.Tag = myControls


     'panel

                newpanel = New Panel

                With newpanel

                    .Tag = dv(x).Item("eu_order_id")

                    .Size = New System.Drawing.Size(900, 28)

                    .Location = New System.Drawing.Point(16, k)

                    .BackColor = System.Drawing.Color.LemonChiffon

                End With


    'WHERE IS "llabel" CREATED AT   IS THAT CODE MISSING IN THE EXAMPLE
    'YOU ONLY NEED THIS CODE IN YOUR LOOP IF YOU ARE CREATING A NEW
    '"llabel" OBJECT EACH TIME...
                AddHandler llabel.Click, AddressOf dostuff



    newpanel.Controls.Add(newtextbox)

    newpanel.Controls.Add(newtextbox1)

    newpanel.Controls.Add(newbutton)

     Me.Controls.Add(newpanel)

                k += 32

            Next

        End Sub



    Now that your Button's tag property holds an array of controls, you can access each associated control in the array.

  • Event for Dynamically Created Controls