Referencing controls in code

hog

Senior Contributor
Joined
Mar 17, 2003
Messages
984
Location
UK
I have a tab control with a selection of textbox controls on each tab page. I am attempting to cycle through each page to assign a value to a textbox on each tap page. If each textbox is named txtDueDate1, txtDueDate2, txtDueDate3 etc how can I cycle through them in a loop? The controls object wants a integer index, I cannot find a way to reference by name. I am going to be stuck completely when I try to assign values to all other controls on each page as the index values are all over the show?

HELP.....PLEASE :-(
 
A couple of questions/suggestions:

First a question: why not just use txtDueDate2.Text = "value"? Why must you use them as a control array? If you're creating them by hand, you can use the same name for each control...

Another question: If the controls are having the same value (just a guess?) why not move the textbox outside the tabpage so that you don't need multiple versions?

Now a suggestion: as you loop through the Controls array, you can check each control name (a string) against the name you're looking for. If it matches, you have your index. Don't forget that if you your textbox is in a groupbox on a tabpage, you'll have to look in the TabPage's Controls collection to find the groupbox, then loop through that control's Controls collection. You may just want a recursive loop.

One more suggestion: If you DO know the control by name, such as txtDueDate1, you can bind the text of that control to the text property of another control. For example, suppose you have textBox1 and textBox2 and you want to keep textBox2 in sync with textBox1. You can use this line of code in Form_Load (or wherever you want):
C#:
// The first "Text" is the Text property on textBox2, the property you're binding
// the second "Text" is the property on textBox1 that you want to bind from
textBox2.DataBindings.Add("Text", textBox1, "Text");

-Nerseus
 
You'll have to create a name-value collection yourself and add the controls at runtime at the start of your application. I don't see why you have to do this, but that's probably what you want to do.

The alternative is to actually create the controls at runtime too, but then you have to deal with positioning them manually.

[edit]Damn, I was beaten to it[/edit]
 
OK, here goes...

I have a Tab Control with 12 Tab Pages all with the same fields but ending in their Tap Page number, ie txtDueDate1, txtDueDate2 etc. As a user selects a record the data returned will determine how many Tab Pages will be enabled. Once this occurs I need to populate each Tab Page with the data relevant to each due date page. I have been reading in the VB .Net help that the ControlsCollection only allows accessing by index number now which is proving a bind. If for example I have 20 contols on each of the 12 pages I do not want to have to cycle through them like 'for each textbox in controls - if name = '' etc as this will be grossly ineffiecient.

Any ideas?
 
Actually, it's not that inefficent to loop through every control. But I can see your point of not *wanting* to do that. In that case, you should look at some of divil's suggestions.

Have you actually done any code yet, by the way? I'm asking because you say you want to disable certain tabs which isn't possible with the built-in Tab control. You can hide tabs (remove TabPages from the TabControl), but not disable. Also, how did you plan on referencing your TabPages by number? You'll have the same issue of looping through all the controls to find one by name (granted, you can loop through the TabControl's Controls collection - very fast).

Can I assume that each tab page has pretty much the same controls, all named sequentially? If so, you might do better to put the controls in a UserControl. Then you only have to find one control by name (UserControl1 for instance) and reference all the child controls by name (txtDueDate - no sequence number).

-Ner
 
Did you read what we both said? You could cycle through them once and add them to a hashtable to associate names with controls, if you really must access them this way.

[edit]Bah, and again![/edit]
 
Sorry, Divil just saw you posting....

I'm trying to do something like this

For intX = o to UBound(arrDates)-1

Me.Controls(Me.Controls.IndexOf("txtDueDate" & intX)).Text = arrDates(intX,0)

Next

Obviuosly doesn't work due to String in IndexOf. Why has MS removed the ability to access via name??
 
Hi,

this is how I enable/disable required tab pages:


' enable required tab pages

For intX = 0 To m_objContract.Frequency

Me.tbcJobs.TabPages.Item(intX).Enabled = True

Next

' disable the rest, but leave summary enabled

For intX = m_objContract.Frequency To Me.tbcJobs.TabPages.Count - 2

Me.tbcJobs.TabPages.Item(intX).Enabled = False
Next

Works a treat?

I will read up on UserControl and Hash?
 
Just a thought here....

You both seem to think that this is a weird thing I'm trying to achieve? How would you tackle this prblem then, re control referencing?

Ta
 
Heiko, no that won't work as the user needs to input data. The idea is each tab page represents a service date whereby the user inputs service data.
 
I don't see the difference between entering data on a tab page and entering data in a groupbox.

Of course you have to update the listview on changes in the details. Of course you have to update the details on selection changes in the listview. Of course you have to keep track of possible changes in the details, in case the selection in the listview changes.

We're doing it like that over here and it rocks.


:)

I think.
 
You must be using the ActiveX version of the Tab control? The .NET version doesn't support an Item property off the TabPages collection (that I can see)...

Unless you're coding everything in a loop (referencing ALL controls on every tab in a loop), I still don't see why you can't reference each control by name? Why not use txtDueDate1, txtDueDate2, etc.? If you ARE using a loop, there are a number of suggestions above... I guess I just don't see the issue.

-Nerseus
 
Mmm, me thinks I probably am not explaining myself?

If for example a user selects a record which requires 4 tab pages of info then I need to restrict the code to updating of 4 pages only. So if I have a loop going from 1 to 4 the loop as you say would reference them by name, but what of the next record the user selects which only has 2 pages required? Then the other pages 3 and four would still be being referenced in the loop?
 
Hi,

ok a kind of version on some suggestions made. I have decided to run some code to obtain the indexes of the controls on the tab pages, I only need to do this once during development. I will then store these into arrays as the form opens and use the arrays in my loops to reference required controls. Messy I know but there you go. I read about hashtables and this seems pretty much the same result as what I'm doing, but with more work. The usercontrol option is too much like hard work at this stage as well as the fact I would still have the same problem referencing only the required controls following each user selection. Heiko I think you are in tune with my problem :-)
 
I still favour the array approach, however MS is making my life hell at the moment due to this reference by index only!!

I can cycle through all the controls and display the name of each control, but am unable to obtain their index???

If I messagebox a textbox for example using:

Messagebox.Show(me.txtDueDate1.Text)

I get the text. If I then try any number of ways to get the index of this control I get -1, control not found!

Messagebox.Show(Me.Controls(Me.Controls.IndexOf(Me.txtDueDate1))

HELP!!! Anybody.....
 
Controls.IndexOf(myControl) will give the index of any control in the collection. What exactly is the problem with this?

And also, you said you didn't want to bother with a hash table, but from what I can see it would simplify your situation. You could add all your controls to it like this:

C#:
Hashtable h = new Hashtable();

foreach (Control c in Controls)
{
	h.Add(c.Name, c);
}

// You can now access your controls directly by name:
((Control) h["mycontrol1"]).Text = "blah";

Visual Basic:
Dim h As New Hashtable()
Dim c As Control

For Each c In Controls
    h.Add(c.Name, c)
Next

'You can now access your controls directly by name:
DirectCast(h("mycontrol1"), Control).Text = "blah"
 
Back
Top