Referring to a control from a string variable

Spektre

Newcomer
Joined
Jul 26, 2003
Messages
19
Hello,

Intro:
As I am missing my old Control Array functionality (its just not as good in .Net in my opinion) I am trying to find a workaround. I have seen the MS suggested way of creating "control arrays" at run time and I prefer the old design time way.

Question:
Is there a way to change a control's property given that you have the control's name in a string variable? For example, through other methods in my function I can find the "Index" calling my event handler for the array. Let's say I have 3 buttons cmd1, cmd2, cmd3 and 3 textboxes text1, text2 and text3.

I want the textbox to read "Hello" when its correspnding button is clicked.

By parsing the last digit of sender.name in a event handler for the buttons I can get my "index". Let's say, button 3 is pressed. I parse sender.name, and get "3". I can then easily set a string to "textbox" & "3".

So now I have a string with a value of "textbox3". How can I take that and set textbox3.Text = "Hello"?

Thanks.

Spektre
 
I'm not sure I understand you, do you wanna use the same event handler for i.e all those buttons. But have it only change the text of it's corresponding textbox?

Well, not sure there's a better way but at the top of my head; have you considered looping all controls for textboxes and checking if it bares the right name or tag?
 
Yes, that is correct. I want to have one event handler for all the buttons, but then only to update the corresponding text box. But the main thing I am looking for is given that you have the name of a control in a string, how can you use that to update the control's properties.

i.e.

Dim ControlName As String
ControlName = "TextBox1" ' TextBox1 is a control on the form
ControlName.Text = "Hello" ' Obviously does not work.

Thanks.


Varghjärta said:
I'm not sure I understand you, do you wanna use the same event handler for i.e all those buttons. But have it only change the text of it's corresponding textbox?

Well, not sure there's a better way but at the top of my head; have you considered looping all controls for textboxes and checking if it bares the right name or tag?
 
If I understand you correctly, you have to first get your hands on a reference to that textbox.

The easiest way I'm guessing would be to (psuedo code):

foreach(Control C in Controls)
{
If C.Name is what you want, using substring() or EndsWith() to check for that number
Then cast the control to a textbox; TextBox MyBox = (TextBox)C;
And now we can MyBox.Text = "Bla bla bla bla";
break; // break out of loop since we're done...
}

That should work. I didn't write much real code, becouse I only know C#.
 
Spektre said:
I want to have one event handler for all the buttons, but then only to update the corresponding text box.

Try
Code:
Private Sub CommandClickHandler(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmd1.Click, cmd2.Click, cmd3.Click, cmd4.Click, cmdNone.click
    if sender is cmd1 then 
        text1.text="Yo button 1"
    elseif sender is cmd2 then 
        text2.text="Yo button 2"
    elseif sender is cmd1 then 
        text3.text="Yo button 3"
    elseif sender is cmd1 then 
        text4.text="Yo button 4"
    else
        msgbox ("No button")
    end if
End Sub

HTH
/Kejpa
 
Close...but in VB?

Yes, this is basically the idea. The part I don't know how to do however is the VB syntax for TextBox MyBox = (textbox)C;


Varghjärta said:
If I understand you correctly, you have to first get your hands on a reference to that textbox.

The easiest way I'm guessing would be to (psuedo code):

foreach(Control C in Controls)
{
If C.Name is what you want, using substring() or EndsWith() to check for that number
Then cast the control to a textbox; TextBox MyBox = (TextBox)C;
And now we can MyBox.Text = "Bla bla bla bla";
break; // break out of loop since we're done...
}

That should work. I didn't write much real code, becouse I only know C#.
 
Thought of this but...

Hi,

Yes, I thought of doing that however this type of code will be used in many places in my app, and the number of "buttons" and corresponding "textboxes" are dozens. Makes for very long If then blocks. So, I was hoping for a more algortihm based approach where I can build up the control's name in a string and access it that way.

Thanks.

kejpa said:
Try
Code:
Private Sub CommandClickHandler(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmd1.Click, cmd2.Click, cmd3.Click, cmd4.Click, cmdNone.click
    if sender is cmd1 then 
        text1.text="Yo button 1"
    elseif sender is cmd2 then 
        text2.text="Yo button 2"
    elseif sender is cmd1 then 
        text3.text="Yo button 3"
    elseif sender is cmd1 then 
        text4.text="Yo button 4"
    else
        msgbox ("No button")
    end if
End Sub

HTH
/Kejpa
 
Spektre said:
Yes, this is basically the idea. The part I don't know how to do however is the VB syntax for TextBox MyBox = (textbox)C;

I can't really code VB, but from what I can see from quick googling perhaps you could use either "CType()" or "DirectCast()" to do the casting.

I don't have VB support installed in my VS.Net so I can't check if it works.

To make the looping even more fail safe you could also use "If TypeOf C Is TextBox Then" before checking if .Name is good.

See link:
http://64.233.183.104/search?q=cach...NET.asp+VB.net+casting&hl=en&client=firefox-a
 
a feature that I exploited in Delphi, which is now available in VB.NET is the tag property. . .

in the property designer, set the tag for the button to the corresponding text box. set the tag for the text box to an enumeration. Given you have a functiion that retunrs a string based on an enumeration, then in your handler:

Code:
Dim ctrl as Control
Dim tag as Control
dim anEnum as MyEnum
 
if sender is Control then 
  ctrl = DirectCast(sender, Control)
  if ctrl.Tag is Control then
	tag = DirectCast(ctrl.Tag, control)
	if tag.Tag is MyEnum then
	   anEnum = DirectCast(tag.Tag, MyEnum)
	   tag.Text = GetEnumString(MyEnum)
	end if
  end if
end if
 
Hmm, it still seems to be going at it backwards.

I would like, given the name of a control, to operate on the control with that name.

Every method I have found, or has been provided here, works backward at this by testing each and every control to see if it has that name and then you can act on it once found. It seems fairly inefficient if you have a large number of controls to do this for (as woudl be the case if you want Control Array fucntionality).

Is there any more direct way?

Thanks again,

Spektre

EDIT--

Well knowing better keywords to search on from the answers given here has enabled me to see I am not alone. This question has come up over and over again in many forms on this and other .Net help forums. It seems that you simply cannot do it in .Net.

To anyone finding this at thread first, you may stop looking for a direct method. It appears not to exist. You must take the performance hit and either loop through the controls or if the controls are known at runtime, make a table of them in code.

Spektre
 
Last edited:
You could listen for every control added to the form and then add it's reference to a hashtable. Then simply ((TextBox)hashTable["textbox1"]).Text = "bla bla bla";

Computers are pretty fast, I can't belive there should be an een noticible performance hit even if you had over 1000 textboxes. And Hashtable itself is _extremly_ fast.
 
Spektre said:
Hmm, it still seems to be going at it backwards.

I would like, given the name of a control, to operate on the control with that name.

Every method I have found, or has been provided here, works backward at this by testing each
[snip]

To anyone finding this at thread first, you may stop looking for a direct method. It appears not to exist. You must take the performance hit and either loop through the controls or if the controls are known at runtime, make a table of them in code.

Spektre
ummm. . . no. . . we are saying looking up a control that by name is NOT direct. . .

this is direct. . .
Code:
Dim ctrl as Control
Dim tag as Control
dim anEnum as MyEnum
 
if sender is Control then 
ctrl = DirectCast(sender, Control)
if ctrl.Tag is Control then
	tag = DirectCast(ctrl.Tag, control)
	if tag.Tag is MyEnum then
	 anEnum = DirectCast(tag.Tag, MyEnum)
	 tag.Text = GetEnumString(MyEnum)
	end if
end if
end if

it says associate the text box with a button:

AButton1.Tag = ATextBox1
AButton2.Tag = ATextBox2
AButton3.Tag = ATextBox3
AButton4.Tag = ATextBox4

associate the textbox with some enumeration

ATextBox1.Tag = MyEnums.Enum1
ATextBox1.Tag = MyEnums.Enum2
ATextBox1.Tag = MyEnums.Enum3
ATextBox1.Tag = MyEnums.Enum4

associate the enumerationations with a string
Code:
Public Enum MyEnum
Enum1
Enum2
enum3
End Enum
Public Class Enums
Shared enumStrings() As String = New String() {"Enum 1", "Enum 2", "Enum 3"} 
Public Shared ReadOnly Property Strings(ByVal anEnum As MyEnum)
	Get
	 Strings = enumStrings(anEnum)
	End Get
End Property
End Class

actually my Event handler should have used the TypeOf operator

see attached vb app
 
Last edited:
Yeah, as I said, make a table of them at runtime....Indirect.


Joe Mamma said:
ummm. . . no. . . we are saying looking up a control that by name is NOT direct. . .

this is direct. . .
Code:
Dim ctrl as Control
Dim tag as Control
dim anEnum as MyEnum
 
if sender is Control then 
ctrl = DirectCast(sender, Control)
if ctrl.Tag is Control then
	tag = DirectCast(ctrl.Tag, control)
	if tag.Tag is MyEnum then
	 anEnum = DirectCast(tag.Tag, MyEnum)
	 tag.Text = GetEnumString(MyEnum)
	end if
end if
end if

it says associate the text box with a button:

AButton1.Tag = ATextBox1
AButton2.Tag = ATextBox2
AButton3.Tag = ATextBox3
AButton4.Tag = ATextBox4

associate the textbox with some enumeration

ATextBox1.Tag = MyEnums.Enum1
ATextBox1.Tag = MyEnums.Enum2
ATextBox1.Tag = MyEnums.Enum3
ATextBox1.Tag = MyEnums.Enum4

associate the enumerationations with a string
Code:
Public Enum MyEnum
Enum1
Enum2
enum3
End Enum
Public Class Enums
Shared enumStrings() As String = New String() {"Enum 1", "Enum 2", "Enum 3"} 
Public Shared ReadOnly Property Strings(ByVal anEnum As MyEnum)
	Get
	 Strings = enumStrings(anEnum)
	End Get
End Property
End Class

actually my Event handler should have used the TypeOf operator

see attached vb app
 
Have you solved the problem yet btw?.. -- been a while since I've been here.

PS.. Why don't you just create your _own_ version of a control-array or whatever it's called. Make a class with a hashtable in it to wrap and hold references to all controls of a partiqular type. Make methods to edit the controls like setText("MyTxtBox","new text") and have it change the text in the textbox that is references/stored in the hashtable -- via key of textbox's name. Hashtable's are insanly fast, and if you for each textboxadded to the control add it to the hashtable -- by means of listening for added controls, start listening _before_ all the textboxes is added -- you won't even have to manually add them.. which if I'm not incorrect was the whole point?.. since your gonna have so many of them..

That's what I think i'd do..... if you have already cracked it then feel free to ignore this :).
 
Back
Top