StrataFrame Forum

Text Boxes with Similar Names txt1, txt2 and so forth

http://forum.strataframe.net/Topic14395.aspx

By Terry Bottorff - 2/15/2008

I have several text boxes on a SF win Form with similar names txt1 through txt10 and I have an array ar(0) through ar(9) that has integers stored. I would like to set up a loop that would let me store the following:



me.txt1.text = ar(0)

me.txt2.text = ar(1)



and so forth. Is there a way to do this using a loop of some sort? I also know I need to convert the integers to strings I think. TIA.
By Greg McGuffey - 2/15/2008

Assuming the controls are all in the same parent container, it would be pretty easy:



' For ease, lets say they are all on the form itself...

' I can't remember if Length gives the actual length or the upper bound

' I'm assuming here it is the actual number of elements.

For idx As Integer = 0 To ar.Length() - 1

'-- I'm just typing this so you might need to cast to text boxes, not sure if Control has Text property

Me.Controls("txt" & idx.ToString()).Text = ar(idx).ToString()

Next




As mentioned, I just typed this, so there might syntax errors or casting issues. The important thing is that controls/components that are containers have a Controls collection that you can use.
By Trent L. Taylor - 2/15/2008

Greg's idea is good and may work best depending upon your circumstances. You could also create an internal collection of the items as well:

Dim myControls As New System.Collections.Generic.List(Of SYstem.WIndows.Forms.Control)

myControls.Add(txt1)
myControls.Add(txt2)
myControls.Add(txt3)

For each ctrl as System.Windows.Forms.Control in myControls
   '-- do whatever you need with the control
   ctrl.Enabled = False
Next

By Terry Bottorff - 2/18/2008

I got Trent's working but I did not get Greg's to work. When I get to this statement it keeps telling me that a am dealing with a Null but when I put a break point in and check that values they are all there and as they should be so I am not sure what is causing it.



Me.Controls("txt" & idx.ToString()).Text = ar(idx).ToString()



I would like to use your way Greg because it would certainly be shorter but since it is working I am safe for the moment. If either of you have a thought as to what I should check for the error please let me know. Thanks again for the great fast help.
By Keith Chisarik - 2/18/2008

I have found that looping through the controls on SF forms is not as straightforward as on a vanilla winform, the controls are not a member of the Me.controls collection. You may want to stick to Trent's suggestion, otherwise it can be a lot of work to loop through all the container objects on a SF form to get to your bound controls.
By StrataFrame Team - 2/18/2008

You could also use the BoundControls property of the BusinessLayer class if all of the textboxes are bound to the same business object.  However, any time you use a collection of controls that you do not maintain (something besides your code put the objects in the collection), you're not guaranteed that the controls will be in any particular order.  So, it's best to have some code that dumps the controls into your own collection in the order in which you want them, and then loop through that collection.
By Terry Bottorff - 2/18/2008

OK I understand and that is OK since I got it working Trents way and that is cool. But, is there a way to put this in a loop instead of typing them all?

myControls.Add(txt1)
myControls.Add(txt2)
myControls.Add(txt3)

I tried this but it would not work

for cnt = 1 to 40

cntrl = "txt" & cnt.tostring()

myControls.Add(cntrl)

next cnt

Thanks again.

By Greg McGuffey - 2/18/2008

Terry Bottorff (02/18/2008)
OK I understand and that is OK since I got it working Trents way and that is cool. But, is there a way to put this in a loop instead of typing them all?



myControls.Add(txt1)

myControls.Add(txt2)

myControls.Add(txt3)



I tried this but it would not work



for cnt = 1 to 40



cntrl = "txt" & cnt.tostring()



myControls.Add(cntrl)



next cnt



Thanks again.




You need to put the actual controls into the list/array, rather than the name of the control. I.e. in you top example, you are putting the actual control into the collection and within the loop you are putting the name into the collection. If you use the method Trent/Ben are suggesting, you will need to put them in individually, then after that you can easily loop through the collection to do whatever you need to them. Best bet would be to have a private method to just load them, then you have one place to update if you change the controls being loaded. If you want to loop, then you need to know what container they are in and you could use the method I suggested, to use a loop to build the names. A third option would be to loop, create the controls (not the name, but the actual control), add them to your collection and add them to the appropriate container on the form.



After reading this, I'd suggest you definitely use your own collection to do manage the controls. As mentioned, you can get into trouble if the controls are in different containers etc. If you use your own collection and then have a method to load that collection, you can then mess with how you are loading it, but the rest of your code is unaffected. Hope that makes sense.
By Trent L. Taylor - 2/18/2008

Really, automating the process is better by creating a recursive method like Greg was talking about.  And instead of testing on a name, if you know the control type or if a certain value on that control will be set, you could test on it instead of a name:

Private Function GetTextControls(Byval testControls As ControlCollection) As System.Collection.Generic.List(Of Control)
    '-- Establish Locals
    Dim r As New List(Of Control)

    For each ctrl As Control in testControls
        '-- Check for a textbox type
        If ctrl.GetType().IsSubClassOf(GetType(System.Windows.Forms.TextBox)) Then
             '-- Add the control to the collection
             r.Add(ctrl)
        End If

       '-- See if there are additional children to check for
       If ctrl.Controls.Count > 0 Then r.AddRange(GetTextControls(ctrl.Controls))
    Next
End Function

Then you could call the method in the form constructor or load like this:

'-- Get all of the text controls
r.AddRange(GetTextControls(Me.Controls))

'-- Then add your logic to cycle through the collection and do whatever you need to
For each ctrl as Control in r
    ctrl.Enabled = False
Next