שתף באמצעות


How to use CONTROLS.FIND method?

Question

Wednesday, January 30, 2013 10:27 AM

Hi ALL:

I put 7 textbox on my form ,now i want to get them in an array like this:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim tr() As TextBox = Me.Controls.Find("train", True)
        Label1.Text = tr.Length
    End Sub

Thank You!

All replies (24)

Wednesday, January 30, 2013 11:16 AM ✅Answered

Hi,

maybe you should read this: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.controlcollection.find%28v=vs.80%29.aspx

You can use this method only by using the name of the control.

Hannes

If you have got questions about this, just ask.

In a perfect world,
users would never enter data in the wrong form,
files they choose to open would always exist
and code would never have bugs.

C# to VB.NET: http://www.developerfusion.com/tools/convert/csharp-to-vb/


Wednesday, January 30, 2013 12:11 PM ✅Answered

Hello,

First off it would be prudent to set Option Strict On either at the code of the form or under project properties with a warning that lines like you second line of code will be an error but easily fixed via an IDE suggestion.

I would suggest placing these into a List because accessing and working with them is easier, of course it all depends on why they are in a container in the first place.

Dim TextBoxs = (From T In Me.Controls.OfType(Of TextBox)() Select T).ToListIf TextBoxs.Count > 0 Then    For Each tb In TextBoxs        Console.WriteLine(tb.Name)    Next    Me.Text = TextBoxs.Count.ToStringEnd If

If you rather do an array

Dim TextBoxs = (From T In Me.Controls.OfType(Of TextBox)()).ToArrayIf TextBoxs.Count > 0 Then    For Each tb In TextBoxs        Console.WriteLine(tb.Name)    Next    Me.Text = TextBoxs.Count.ToStringEnd If

Lastly, say you only want specific TextBox controls that their name begins with txt.

Dim TextBoxs = (From T In Me.Controls.OfType(Of TextBox)() Where T.Name.StartsWith("txt") Select T).ToListIf TextBoxs.Count > 0 Then    For Each tb In TextBoxs        Console.WriteLine(tb.Name)    Next    Me.Text = TextBoxs.Count.ToStringEnd If

kevininstructor


Wednesday, January 30, 2013 12:17 PM ✅Answered

Okay, my first reply will get all TextBox controls that reside on the form but let's say there are some child containers such as panels that have TextBox controls on them. The code I provided will not get them as is and rightfully so. If you wanted to get TextBox controls on a panel we use Panel1.Controls.Find.

If you simply want all TextBoxs on the form and any child container.

Form code

Dim TextBoxs = (From T In AllControls().OfType(Of TextBox)()).ToListIf TextBoxs.Count > 0 Then    For Each tb In TextBoxs        Console.WriteLine(tb.Name)    Next    Me.Text = TextBoxs.Count.ToStringEnd If

The following is required for the last code section and must be in a code module.

<System.Diagnostics.DebuggerStepThrough()> _<System.Runtime.CompilerServices.Extension()> _Public Function AllControls(ByVal container As Control) As IEnumerable(Of Control)    Dim Controls = New List(Of Control)    AddChildControls(Controls, container)    Return ControlsEnd Function<System.Diagnostics.DebuggerStepThrough()> _Private Sub AddChildControls(ByVal list As List(Of Control), ByVal container As Control)    For Each ctl As Control In container.Controls        list.Add(ctl)        If ctl.Controls.Count > 0 Then            AddChildControls(list, ctl)        End If    NextEnd Sub

kevininstructor


Wednesday, January 30, 2013 1:44 PM ✅Answered

Hi ALL,

It should be noted that the FIND method returns an array of Type CONTROL

which CAN NOT be used like this if you have OPTION STRICT ON.

>>

Dim textBoxesArray() As TextBox = Me.Controls.Find("train", False)

and you can not do this either.>>

Dim textBoxesArray() As TextBox = CType(Me.Controls.Find("train", False), TextBox())

Additionally "train" would be searched for, for an exact match for a control called train

'

Without using LINQ as used in later versions of VB.Net you would have to use some code

like this to find all of the controls containing the word train in their Name property.

On Form1 I have the following controls;

  • 1 Button named Button1
  • 3 TextBoxes named train1 , another_trainComing , bluetrain

'

Option Strict On

Public Class Form1

    Public new_Line As String = System.Environment.NewLine

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        For Each ctrl As Control In Me.Controls
            If TypeOf (ctrl) Is TextBox Then
                If ctrl.Name.IndexOf("train") >= 0 Then
                    MessageBox.Show("Found...." & new_Line & new_Line & ctrl.Name)
                End If
            End If
        Next

    End Sub
End Class
Regards,

Click this link to see the NEW way of how to insert a picture into a forum post.

Installing VB6 on Windows 7

App Hub for Windows Phone & XBOX 360 developers.


Wednesday, January 30, 2013 5:20 PM ✅Answered | 1 vote

Well, you can put your textbox's in array by this (suppose all your textbox on the form, not in container or groupbox)

Dim artxt(6) As TextBoxartxt(0) = Me.Controls("train")artxt(1) = Me.Controls("TextBox2")artxt(2) = Me.Controls("TextBox3")artxt(3) = Me.Controls("TextBox4")artxt(4) = Me.Controls("TextBox5")artxt(5) = Me.Controls("TextBox6")artxt(6) = Me.Controls("TextBox7")

For your later-on question about 10 combo's with 10 checkbox's

Add the combo's and checkbox's in a way to be arranged by name
Combobox1, checkbox1
Combobox2, checkbox2
....
Combobox10, checkbox10

I did it with 4, so you had to add the rest in sub_combobox1_selectedIndexchanged (....) handles at the end

Sub ComboBox1_SelectedIndexChanged( ByVal sender As System.Object,  ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged,ComboBox2.SelectedIndexChanged,ComboBox3.SelectedIndexChanged,ComboBox4.SelectedIndexChanged        Dim sender_name = CType(sender, ComboBox).Name        ' remove all characters and leave the digits        For Each ch As Char In sender_name            If Not Char.IsDigit(ch)                sender_name = sender_name.Replace(ch,"")            End If        Next        Dim sender_num = sender_name        Me.Controls("checkbox" + sender_num.ToString).Enabled = True    End Sub

Blog: http://samir-ibrahim.blogspot.com/

Actually with Lambda you can do this with one line of code in the SelectedIndexChange event when there is a matching CheckBox for a ComboBox i.e. CheckBox1, ComboBox1.

Hence the one line is broken down to allow easy reading.

Private Sub ComboBox1_SelectedIndexChanged(    ByVal sender As System.Object,    ByVal e As System.EventArgs) _Handles _    ComboBox1.SelectedIndexChanged, _    ComboBox2.SelectedIndexChanged    Me.Controls.OfType(Of CheckBox)().Where( _        Function(c) _            c.Name.Last = CType(sender, ComboBox).Name.Last) _        .First.Enabled = CType(sender, ComboBox).SelectedIndex = 0End Sub

kevininstructor


Thursday, January 31, 2013 3:02 PM ✅Answered | 2 votes

I found this solution classic,and i added some lines,it works!

Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged, ComboBox2.SelectedIndexChanged, ComboBox3.SelectedIndexChanged, ComboBox4.SelectedIndexChanged, ComboBox5.SelectedIndexChanged
        Dim sender_name = CType(sender, ComboBox).Name
        Dim currentCtrl As ComboBox = CType(sender, ComboBox)
        ' remove all characters and leave the digits
        For Each ch As Char In sender_name
            If Not Char.IsDigit(ch) Then
                sender_name = sender_name.Replace(ch, "")
            End If
        Next
        Dim sender_num = sender_name
        If currentCtrl.SelectedIndex = 1 Then
            Me.Controls("checkbox" + sender_num.ToString).Enabled = False
        Else
            Me.Controls("checkbox" + sender_num.ToString).Enabled = True
        End If
    End Sub

Wednesday, January 30, 2013 1:02 PM

Hi ALL:

I put 7 textbox on my form ,now i want to get them in an array like this:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim tr() As TextBox = Me.Controls.Find("train", True)
        Label1.Text = tr.Length
    End Sub

Thank You!

Jeson,

What you want to do?

  1. put 7 textboxes in an array, that is plain easy
  2. use that code, with that you don't get those 7 textboxes in an array, only those with the name train which are somewhere in a controlcollection of controls.

The answer on 1 is 

dim tr = "train1, train2.......................trrain7}

 

Success
Cor


Wednesday, January 30, 2013 2:48 PM

Kevininstructor:

Thank you for your detailed answers.It's quite useful and it set me thinking..But my real condithion is that I get 10 comobox named as combobox1,combobox2,combobox3...and 10 checkbox named as checkbox1,checkbox2,checkbox3...in a form.

I wish to achieve function that if one of the combobox selectedIndex=0,for example combobox1,then checkbox1.enable=false

if combobox2 selecteditemchaged then checkbox2.enable=false

...

the current solution is like code below ,of course im not satisfied with this

Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
        If ComboBox1.SelectedIndex = 0 Then
            CheckBox1.Enabled = False
        End If
    End Sub

    Private Sub ComboBox2_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox2.SelectedIndexChanged
        If ComboBox2.SelectedIndex = 0 Then
            CheckBox2.Enabled = False
        End If
    End Sub...

 I tried to define a control collection and set a Hashtable but failed,would you please give me some suggestion?

Thank you sincerely!


Wednesday, January 30, 2013 3:34 PM

Try this example which is VS2010 syntax.

Public Class Form1    Private Sub Button1_Click(        ByVal sender As System.Object,        ByVal e As System.EventArgs) _    Handles Button1.Click        ComboBox1.SelectedIndex = 1    End Sub    Private Sub Button2_Click(        ByVal sender As System.Object,        ByVal e As System.EventArgs) Handles Button2.Click        ComboBox2.SelectedIndex = 1    End Sub    Private Sub ComboBox1_SelectedIndexChanged(        ByVal sender As System.Object,        ByVal e As System.EventArgs) _    Handles ComboBox1.SelectedIndexChanged, ComboBox2.SelectedIndexChanged        Dim x =            (                From T In Me.Controls.OfType(Of CheckBox)()                Where T.Name.Last = CType(sender, ComboBox).Name.Last                Select T            ).First        x.Enabled = CType(sender, ComboBox).SelectedIndex = 0    End Sub    Private Sub Form1_Load(        ByVal sender As System.Object,        ByVal e As System.EventArgs) Handles MyBase.Load        Dim Items1 As New List(Of String) From {"A", "B", "C", "D"}        Dim Items2 As New List(Of String) From {"AA", "BB", "CC", "DD"}        ComboBox1.DataSource = Items1        ComboBox2.DataSource = Items2    End SubEnd Class

kevininstructor


Wednesday, January 30, 2013 5:02 PM

Well, you can put your textbox's in array by this (suppose all your textbox on the form, not in container or groupbox)

Dim artxt(6) As TextBox

artxt(0) = Me.Controls("train")
artxt(1) = Me.Controls("TextBox2")
artxt(2) = Me.Controls("TextBox3")
artxt(3) = Me.Controls("TextBox4")
artxt(4) = Me.Controls("TextBox5")
artxt(5) = Me.Controls("TextBox6")
artxt(6) = Me.Controls("TextBox7")

For your later-on question about 10 combo's with 10 checkbox's

Add the combo's and checkbox's in a way to be arranged by name
Combobox1, checkbox1
Combobox2, checkbox2
....
Combobox10, checkbox10

I did it with 4, so you had to add the rest in sub_combobox1_selectedIndexchanged (....) handles at the end

Sub ComboBox1_SelectedIndexChanged( ByVal sender As System.Object,  ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged,ComboBox2.SelectedIndexChanged,ComboBox3.SelectedIndexChanged,ComboBox4.SelectedIndexChanged
        Dim sender_name = CType(sender, ComboBox).Name

        ' remove all characters and leave the digits
        For Each ch As Char In sender_name
            If Not Char.IsDigit(ch)
                sender_name = sender_name.Replace(ch,"")
            End If
        Next
        Dim sender_num = sender_name
        Me.Controls("checkbox" + sender_num.ToString).Enabled = True
    End Sub

Blog: http://samir-ibrahim.blogspot.com/


Thursday, January 31, 2013 7:10 AM

Private Sub ComboBox1_SelectedIndexChanged(
    Me.Controls.OfType(Of CheckBox)().Where( _
        Function(c) _
            c.Name.Last = CType(sender, ComboBox).Name.Last) _
        .First.Enabled = CType(sender, ComboBox).SelectedIndex = 0
End Sub

kevininstructor

That was very very cool

Can you explain in slow motion how this code works? :)

Blog: http://samir-ibrahim.blogspot.com/


Thursday, January 31, 2013 7:59 AM | 1 vote

Hopefully the explaination is not too confusing, sometimes slow motion can inject complexity.

I query from the current form control collection (Me.Controls) for only CheckBox controls via .OfType(Of CheckBox) which applies a where condition using .Where for a CheckBox control that matches the last character of the ComboBox i.e. Function(c) where 'c' is a CheckBox because of .OfType(Of CheckBox) filtered the controls in Me.Controls to only CheckBox controls so in short if the results were CheckBox1, CheckBox2, CheckBox3 and sender is ComboBox2 (which we find out via casting sender as a ComboBox CType(sender, ComboBox) and then using Last language extension on the Name property we end up with 1, 2 or 3 which is matched up when using Function(c) to one of the controls in Me.Controls against names using last thus ending up with 1, 2, or 3. In this case the match returns the object ComoboBox2 against CheckBox2 which we now can access it's properties like Enable. So in the end we set Enable. Now let's say we were not sure there was a one to one match between ComboBox and CheckBox this statement would not be good to use as there are no assertion to allow for no matches which would mean my first reply would be best with a tweak, instead of using "First" we would use FirstOrDefault and then check if the result was Nothing, if nothing this means no match so we could not set Enable but if Not Nothing we can set the Enable property.

Get all CheckBox controls

Me.Controls.OfType(Of CheckBox)()

Here we query the CheckBox controls where c is of type CheckBox

Where(Function(c)

Get the ending character for a CheckBox

c.Name.Last

Match against the ending character in the ComboBox which triggered the event

CType(sender, ComboBox).Name.Last

Here is Last extension from MSDN and check out Lambda function.

kevininstructor


Thursday, January 31, 2013 2:38 PM

That was excellent and slow explanation. Thanks

So, using the Last extension will work from Combobox1 to Combobox10, where If I have Combobox11 it will conflict with Combobox1. 

Is there a way to remove the characters and leave the number using your approach? or, how to do it in case there is Combobox1 and Combobox11?

Blog: http://samir-ibrahim.blogspot.com/


Thursday, January 31, 2013 3:08 PM | 1 vote

Yes, I am sure this can be done. The first part is shown conceptually

Dim MyValue As String = "CheckBox11"Dim Result As Integer = CInt(System.Text.RegularExpressions.Regex.Replace(MyValue, "[^0-9]", ""))Console.WriteLine(Result)

The result variable now contains 11, nothing else. I am not in a position right now to re-write the code to suit this requirement, in the middle of a project at work.

kevininstructor


Thursday, January 31, 2013 3:10 PM | 1 vote

Kevininstructor

I tried Samir Ibrahim's code ,it's useful and  understandable.Thank you for your reply.Honestly i must study it as homework these days.


Friday, February 1, 2013 1:40 PM | 1 vote

Yes, I am sure this can be done. The first part is shown conceptually

Dim MyValue As String = "CheckBox11"
Dim Result As Integer = CInt(System.Text.RegularExpressions.Regex.Replace(MyValue, "[^0-9]", ""))
Console.WriteLine(Result)

The result variable now contains 11, nothing else. I am not in a position right now to re-write the code to suit this requirement, in the middle of a project at work.

kevininstructor

I use it and combine it with your previous Linq and it worked well

        Me.Controls.OfType(Of CheckBox)().Where(Function(c) CInt(Regex.Replace(c.Name, "[^0-9]", "")) = 
                                                            CInt(Regex.Replace(CType(sender, ComboBox).Name, "[^0-9]", ""))).First.Enabled = 
                                                            CType(sender, ComboBox).SelectedIndex = 0

What a line :)

I hope I did not bother you with my question's

Thank you..

Blog: http://samir-ibrahim.blogspot.com/


Friday, February 1, 2013 1:49 PM

No bother, we are all here to learn and grow.

kevininstructor


Friday, February 1, 2013 3:46 PM

Hi,

maybe you should read this: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.controlcollection.find%28v=vs.80%29.aspx

You can use this method only by using the name of the control.

Hannes

If you have got questions about this, just ask.

In a perfect world,
users would never enter data in the wrong form,
files they choose to open would always exist
and code would never have bugs.

C# to VB.NET: http://www.developerfusion.com/tools/convert/csharp-to-vb/

What am I missing about .Find?  Why does this return an array of controls?

"Those who use Application.DoEvents() have no idea what it does and those who know what it does never use it." JohnWein


Sunday, February 3, 2013 2:33 PM

If I want to use the list in deferent sub or function,do I have to write this code every time?

Dim TextBoxs = (From T In Me.Controls.OfType(Of TextBox)() Where T.Name.StartsWith("txt") Select T).ToList

Or is there anyway to claim TextBoxs,so that I can use it repeatly?Thanks!


Sunday, February 3, 2013 2:45 PM

If I want to use the list in deferent sub or function,do I have to write this code every time?

Dim TextBoxs = (From T In Me.Controls.OfType(Of TextBox)() Where T.Name.StartsWith("txt") Select T).ToList

Or is there anyway to claim TextBoxs,so that I can use it repeatly?Thanks!

If you do it like this then TextBoxs will be available in different subs / functions

Public Class Form1

    Dim TextBoxs As IEnumerable

    Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
        TextBoxs = (From T In Me.Controls.OfType(Of TextBox)() Where T.Name.StartsWith("txt") Select T).ToList
        Stop
    End Sub
End Class

"Those who use Application.DoEvents() have no idea what it does and those who know what it does never use it." JohnWein


Sunday, February 3, 2013 7:30 PM

I found this solution classic,and i added some lines,it works!

Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged, ComboBox2.SelectedIndexChanged, ComboBox3.SelectedIndexChanged, ComboBox4.SelectedIndexChanged, ComboBox5.SelectedIndexChanged
        Dim sender_name = CType(sender, ComboBox).Name
        Dim currentCtrl As ComboBox = CType(sender, ComboBox)
        ' remove all characters and leave the digits
        For Each ch As Char In sender_name
            If Not Char.IsDigit(ch) Then
                sender_name = sender_name.Replace(ch, "")
            End If
        Next
        Dim sender_num = sender_name
        If currentCtrl.SelectedIndex = 1 Then
            Me.Controls("checkbox" + sender_num.ToString).Enabled = False
        Else
            Me.Controls("checkbox" + sender_num.ToString).Enabled = True
        End If
    End Sub

But what has it to do with the Control Find. I suggest an moderator to move it to Off Topic as this is misleading those searching for questions around that.

Success
Cor


Monday, February 4, 2013 4:57 PM

I don't understand control.find returning an array. 

"Those who use Application.DoEvents() have no idea what it does and those who know what it does never use it." JohnWein


Monday, February 4, 2013 5:06 PM | 1 vote

dbasnett,

if you place the controls on your form by using the IDE ( editor ) you can`t add more than one control with the same name. But if you add the control by code you can add multiple controls by the same name. So if you then use the control.find method it makes sense to find more than one control.

Hannes

If you have got questions about this, just ask.

In a perfect world,
users would never enter data in the wrong form,
files they choose to open would always exist
and code would never have bugs.

C# to VB.NET: http://www.developerfusion.com/tools/convert/csharp-to-vb/


Monday, February 4, 2013 5:19 PM

dbasnett,

if you place the controls on your form by using the IDE ( editor ) you can`t add more than one control with the same name. But if you add the control by code you can add multiple controls by the same name. So if you then use the control.find method it makes sense to find more than one control.

Hannes

If you have got questions about this, just ask.

In a perfect world,
users would never enter data in the wrong form,
files they choose to open would always exist
and code would never have bugs.

C# to VB.NET: http://www.developerfusion.com/tools/convert/csharp-to-vb/

OIC!  Maybe if I had ever tried it via code, using the same name, I would've known.  Live and learn.

"Those who use Application.DoEvents() have no idea what it does and those who know what it does never use it." JohnWein