problem of controls array in Visual Basic 2005

Hi:

I wrote a project in vb6. 

That project contains controls array and I want to upgrade this project to vb2005 but I have some problems.

In vb6:

 

 

 

I have array of checkbox

When the user check the checkbox  It's index = I as integer  then

Create 3 elements in 3 arrays of combobox

All this elements have the same index

 

 When I want to determine any combobox by the index of checkbox

I will write code like this:

 

    For i = 0 To Check1.UBound

        If Check1(i).Value = vbChecked Then

       

            Rs1.Field1 = Combo1(i).Text

            Rs1.Field2 = Combo2(i).Text

            Rs1.Field3 = Combo3(i).Text

        End If

   

    Next i

 

In VB2005:

No problem when I create the controls in container like groupbox

But I used the tag property instead of index property

 

If Chk.CheckState = CheckState.Checked Then

 

            Dim CB1 As New ComboBox

            Dim Cb2 As New ComboBox

            Dim Cb3 As New ComboBox

 

 

            CB1.Size = New Size(93, 21)

            CB1.Location = New Point(176, Chk.Top)

            CB1.Tag = Chk.Tag

            CB1.Name = "cb1" & Chk.Tag

 

 

            Grl.Controls.Add(CB1)

 

            Cb2.Size = New Size(100, 21)

            Cb2.Location = New Point(292, Chk.Top)

            Cb2.Tag = Chk.Tag

            Cb2.Name = "Cb2" & Chk.Tag

            Grl.Controls.Add(Cb2)

 

            Cb3.Size = New Size(38, 21)

            Cb3.Location = New Point(418, Chk.Top)

            Cb3.Tag = Chk.Tag

            Cb3.Name = "Cb3" & Chk.Tag

            Grl.Controls.Add(Cb3)

 

But when I want to remove row of comboboxes

By this code:

  ElseIf Chk.CheckState = CheckState.Unchecked Then

            For Each Cnl As Control In Grl.Controls

                If Cnl.Tag = Chk.Tag Then

                    If TypeOf Cnl Is ComboBox Then

                        Grl.Controls.Remove(Cnl)

                    End If

                End If

            Next

 

Only Two comboboxes removed ,

Becouse more than one control of controls in groupbox have the same index !!!

 I don’t know why

And I don't know how i can make the groupbox generate the unique index to it's controls

 

And the big problem is:

 

 

 To determine the combobox in groupbox :

 

                   For Each Cnl As Control In GrL.Controls

                        If TypeOf Cnl Is CheckBox Then

                            Chk = CType(Cnl, CheckBox)

                            If Chk.CheckState = CheckState.Checked Then

                               Dim Cb As ComboBox

                             For Each CNL1 As Control In Grl1.Controls

                          If TypeOf CNL1 Is ComboBox Then

                                        Cb = CType(CNL1, ComboBox)

                                           If Cb.Tag = Chk.Tag Then

                                                     ' do somthing 

                                                End If

                                            End If

                                        Next

                            End If

                        End If

                    Next

 

or :

 fix the lenth of string of name property of check boxes and comboboxes.

 

 

For Each Cnl As Control In GrL.Controls

                        If TypeOf Cnl Is CheckBox Then

                            Chk = CType(Cnl, CheckBox)

                            If Chk.CheckState = CheckState.Checked Then

                               Dim Cb As ComboBox

                             For Each CNL1 As Control In Grl1.Controls

                                        If TypeOf CNL1 Is ComboBox Then

                                            Cb = CType(CNL1, ComboBox)

 

                         

                                        If Cb.Name.Substring(3) = _

                                           Chk.Name.Substring(3) Then

                                                      ' do something

End if

                                                End If

                                            End If

                                        Next

                            End If

                        End If

                    Next

 

 when the controls count not less than 500 elements

 

the program performance will be very weak

 

there's any other way to do that

 

 

Thanks for Read

 



Answer this question

problem of controls array in Visual Basic 2005

  • Jim Perry

    For Each Cnl As Control In Grl.Controls

    If Cnl.Tag = Chk.Tag Then

    If TypeOf Cnl Is ComboBox Then

    Grl.Controls.Remove(Cnl)

    End If

    End If

    Next



    The ForEach loop goes through the index from 0 to 2, so the first loop = item with index0, the second loop = item with index1, the third loop = item with index2

    But if you remove itemA during the first loop, then itemB becomes the item at index0 and itemC=index1, so when the foreach loop goes to the second loop, it's looking for item with index1 which is itemC at that time.

    In other words, don't use a ForEach loop if you're removing items - use a For..To.. loop instead.

  • lali.b

    Actually, Blair Allen Stark gave you a hint for linking the parent-checkbox to each child-combobox: by pointing the combobox's tag to the parent-checkbox, you don't have to mess with indexnumbers because the tag points to the whole parent-checkbox object. So you would get this code:
    Combobox1.Tag = CheckBox1

    ------
    I don't quite understand what you mean by 'determine if the control is numerical or not , required or not'.

    -----
    If you only want to save comboboxes that have numerical values (at the start of the text), then use the IsNumeric function: zTrueOrFalse = IsNumeric(combobox1.text)
    Note that the IsNumeric function still returns True if there are words in the text after a number at the start. http://msdn2.microsoft.com/en-us/library/6cd3f6w1.aspx

    -----
    If you want a way to link the parent-CheckBox to its children-comboboxes, then you could use some type of Collection object to store the comboboxes, and make that collection object the Tag of the Checkbox. For Example:

    Dim zHashTable As Hashtable
    Dim zComboBox As ComboBox

    zHashTable = New Hashtable ' This hashtable collection will store the Child-ComboBoxes
    CheckBox1.Tag = zHashTable ' Attach the hashtable-collection to the checkbox' Tag

    zComboBox = New ComboBox ' This adds a new child-combobox
    zComboBox.Tag = CheckBox1 ' Point the new combobox' .Tag to the parent-checkbox

    ' Add the combobox to the GroupBox
    GroupBox1.Controls.Add(zComboBox)

    ' Put the child-combobox into the parent-checkbox's hashtable-collection of children
    ' the zComboBox object is used as both key and value
    zHashTable.Add(zComboBox, zComboBox)

    ' Now removing the Combobox again
    GroupBox1.Controls.Remove(zComboBox)
    zHashTable.Remove(zComboBox)

    Now you have linked each combobox to its parent-checkbox, and each parent-checkbox carries a collection of its child-comboboxes in its own Tag property.



  • alihht

    Blair,

    If you claim "VBsux's" so much. Why do you hang around VB fora to criticize it

    I don't like C languages but I don't go into C fora to criticize the language. It's a lot like going to christian fora to criticize christians. Your role becomes that of a troll. Even with all of your talents, your role in VB fora is often that of a troll.



  • Kenneth Gillen

    mm_ezzo wrote:

    thans blair for yuor replay

    but i have some problem with tag property that's cause me don't use it any more to determine the control

    Actualy i use it to determine if this control is required or not when i validates the controls before saving the data

    i need any other way to detemine the control in array of controls in container

    but first i need the way to set the index to control before i create it and before set the name prperty to it !!

    note: i'm trying to learn C# but i have no time for that .... maybe later

    thanks again

    easy. . .



    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    checkBox1.Tag = new ControlWrapper(textBox1);
    checkBox2.Tag = new ControlWrapper(textBox2);
    checkBox3.Tag = new ControlWrapper(textBox3);
    textBox1.Tag = new ControlWrapper(comboBox1);
    textBox2.Tag = new ControlWrapper(comboBox2);
    textBox3.Tag = new ControlWrapper(comboBox3);
    checkBox1.CheckedChanged += checkBox1_CheckedChanged;
    checkBox2.CheckedChanged += checkBox1_CheckedChanged;
    checkBox3.CheckedChanged += checkBox1_CheckedChanged;
    }

    void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
    CheckBox cb = sender as CheckBox;
    if (cb == null) return;
    ControlWrapper wrapper = cb.Tag as ControlWrapper;
    if (wrapper == null) return;
    TextBox tb = wrapper.Control as TextBox;
    if (tb == null) return;
    wrapper = tb.Tag as ControlWrapper;
    if (wrapper == null) return;
    ComboBox cbo = wrapper.Control as ComboBox;
    if (cbo == null) return;
    tb.Text = cb.Checked cbo.Text : string.Empty;
    }
    }
    public class ControlWrapper
    {
    bool _isRequired = true;
    Control _ctrl;
    public ControlWrapper(Control ctrl, bool isRequired)
    {
    _ctrl = ctrl
    _isRequired = isRequired;
    }
    public ControlWrapper(Control ctrl):base(ctrl, true){};
    public Control Control { get { return _ctrl; }}
    public bool IsRequired { get { return _isRequired;} {set { _isRequired = value;} }
    }




  • maverick_majnoo

    Thanks nogchoco

    i mean by 'determine if the control is numerical or not , required or not'

    actualy i useing module it's contain procedures and functions and use it from the forms :

    like :

    public sub ValidTheForm(ByVal F as Form)

    'for each control in form F do validthecontrol procedure

    end sub

    private sub ValidTheControl( ByVal C as Control)

    if c.tag="m" then ' it's required so show messagebox to user to must fill it.

    if c.tag="i" then ' it numerical and user must insert only numbers

    ' ....................etc

    end sub

    and in the form i write code like this :

    sub save

    validtheform(me)

    end sub

    actualy i have no idea about the the hashtable but i will work with it and i will feedback to u

    Thank You again


  • Blkbird

    The indexproblem is as I described it: removing an item from a collection makes the index of the other items decrease by 1 and so the ForEach loop skips an item because it doesn't take the reordering of the items into account.

    Here's a working example for you. It's a Form1 with 2 checkboxes: Chk (with Tag=1) and Chk2(with Tag=2) and a Groupbox (named Grl). Note that I don't have your complete code, so I had to adapt it slightly to make it work. The eventsub handles checkstatechanges for both checkboxes so I've used "sender" (which is one of the checkboxes) as the object. Just start a new WindowsApplication, add two checkboxes and a groupbox, name and tag them as mentioned, and paste the code below as the code for Form1.

  • Lixin wang

    You're welcome, mm_ezzo

  • Tom_Liu

    thans blair for yuor replay

    but i have some problem with tag property that's cause me don't use it any more to determine the control

    Actualy i use it to determine if this control is required or not when i validates the controls before saving the data

    i need any other way to detemine the control in array of controls in container

    but first i need the way to set the index to control before i create it and before set the name prperty to it !!

    note: i'm trying to learn C# but i have no time for that .... maybe later

    thanks again


  • Donald E. King

    Thanks nogchoco

    hashtable is WonderFull Way to do what i want.....

    thank u


  • stallion_alpa

    actually. . . control arrays were VbSux's way of gettng around some of its major deficiencies.

    the proper way to do this would be to assign the associated textbox to the checkbox.tag and assign the associated combobox to the text box tag

    in a checkedchanged handler cast the sender to a checkbox and cast tthat's tag to a text box and cast thats's tag to a combo box. then set the casted textbox text to the casted combobnoxes tag

    because I can't stand coding in VB, this is in c# but the idea is the same. . . NOTE when you see the code in vb and compare to c# you will see why I dont care for vb.



    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    checkBox1.Tag = textBox1;
    checkBox2.Tag = textBox2;
    checkBox3.Tag = textBox3;
    textBox1.Tag = comboBox1;
    textBox2.Tag = comboBox2;
    textBox3.Tag = comboBox3;
    checkBox1.CheckedChanged += checkBox1_CheckedChanged;
    checkBox2.CheckedChanged += checkBox1_CheckedChanged;
    checkBox3.CheckedChanged += checkBox1_CheckedChanged;
    }

    void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
    CheckBox cb = sender as CheckBox;
    if (cb == null) return;
    TextBox tb = cb.Tag as TextBox;
    if (tb == null) return;
    ComboBox cbo = tb.Tag as ComboBox;
    if (cbo == null) return;
    tb.Text = cb.Checked cbo.Text : string.Empty;
    }
    }



  • djchapin

    Thank u Blair
  • Vivek Uppal

    Thanks nogchoco : for your replay..

    actualy : i tryed to do as u sayed but the problem still persist .

    the problem is : more than one control of controls in groupbox have the same index

    and some indexes missed :

    example : in groupbox it have 50 control but there's no element have index 16 !

    i don't know why

    And your way here will cause error !!

    any way to set the index to elements in container when creates the elements before i set the name to it

    thanks again


  • Simon.Chan

    Hear Hear.....

    Everyone has a personal opinion but I wholeheartedly agree with Renee comment. Expressing your own personal opinions like this in a forum dedicated to the product - only serves to start arguments/flames.

    Whilst you entitled to your opinion I would respectfully request that you dont express them in such a public manner in these forums. It just isnt needed and doesnt add anything to your comments.


  • jeff1024

    Thanks nogchoco

    it's works

    thank you very much

    but could i ask you something else

    i use the tag property for determine if the control is numerical or not , required or not .

     as  a validation method before saving the data

    there's any way else instead of tag property to derermine the control in the container .

    but befor determination i need to set th index to the control before  or when i create it.

     

    Thank you again

     


  • problem of controls array in Visual Basic 2005