Click here to Skip to main content
16,020,565 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm looking how to create a loop that would access each combo box on a form.

I have a form with 10 or so combo boxes. I would like to create a for each loop to either get or set the index of the data set they are associated with as opposed to writing individual code for each box.

Something like:

dim iIndex as int
For Each cbox in me.Combobox
   cbox.item=iIndex
next


What I have tried:

I've look at so many sites to find this solution, here as well. Any possible solutions either do not give me the ability to select the item field or VB.Net indicates an error that I cannot decypher.

Thank-you
Posted
Updated 27-Jun-23 2:46am
v2
Comments
Peter2023 26-Jun-23 7:06am    
Thanks for the response. I have tried this method before and always get the same error

Error BC30456 'Name' is not a member of 'VisualStyleElement.ComboBox'. UIDDB

I have tried combobox.items.clear(), that too has the same error.

Is there a way to be able to do bulk routines like clear, selectedindex etc?

A Form can hold one or more controls in a Collection[^]. You can see this by looking at the Form.Designer.vb class file. For example:
VB
ComboBox1 = New ComboBox()
Button1 = New Button()
TextBox1 = New TextBox()
ComboBox2 = New ComboBox()

' more controls are created here when you add a control to a form

SuspendLayout()
' 
' ComboBox1
' 
ComboBox1.FormattingEnabled = True
ComboBox1.Location = New Point(300, 49)
ComboBox1.Name = "ComboBox1"
ComboBox1.Size = New Size(104, 23)
ComboBox1.TabIndex = 0
' 
' Button1
' 
Button1.Location = New Point(349, 108)
Button1.Name = "Button1"
Button1.Size = New Size(119, 27)
Button1.TabIndex = 1
Button1.Text = "Button1"
Button1.UseVisualStyleBackColor = True
' 
' TextBox1
' 
TextBox1.Location = New Point(357, 160)
TextBox1.Name = "TextBox1"
TextBox1.Size = New Size(91, 23)
TextBox1.TabIndex = 2
' 
' ComboBox2
' 
ComboBox2.FormattingEnabled = True
ComboBox2.Location = New Point(348, 214)
ComboBox2.Name = "ComboBox2"
ComboBox2.Size = New Size(104, 23)
ComboBox2.TabIndex = 3

' more controls are initialized here

' 
' Form1
' 
AutoScaleDimensions = New SizeF(7.0F, 15.0F)
AutoScaleMode = AutoScaleMode.Font
ClientSize = New Size(800, 450)

' the other controls are added here

Controls.Add(ComboBox2)
Controls.Add(TextBox1)
Controls.Add(Button1)
Controls.Add(ComboBox1)
Name = "Form1"
Text = "Form1"
ResumeLayout(False)
PerformLayout()

So we can see when a control is placed on the form, the VS IDE creates the code automatically. Each control is added to the Form1.Controls collection property.

So we need to iterate over this Collection[^] property to access the controls on the form. We can also filter the collection to only return a specific type by using Linq[^] and the OfType[^] extension method:
VB
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    For Each comboBox As ComboBox In Me.Controls.OfType(Of ComboBox)
        ' do work here on each combobox
        Debug.WriteLine(comboBox.Name)
    Next

End Sub

The code above will iterate over only the ComboBoxes on the form, and will display their names in the Locals window. Replace my code with yours.

UPDATE

Here is Microsoft's implementation of the OfType method:
C#
public static IEnumerable<TResult> OfType<TResult>(this IEnumerable source)
{
	if (source == null)
	{
		ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
	}

	return OfTypeIterator<TResult>(source);
}

private static IEnumerable<TResult> OfTypeIterator<TResult>(IEnumerable source)
{
	foreach (object? obj in source)
	{
		if (obj is TResult result)
		{
			yield return result;
		}
	}
}


Here is a VB translation of the Microsoft code above:
VB
Public Shared Function OfType(Of TResult)(ByVal source As IEnumerable) _
As IEnumerable(Of TResult)

    If source Is Nothing Then
        ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source)
    End If

    Return OfTypeIterator(Of TResult)(source)

End Function

Private Shared Iterator Function OfTypeIterator(Of TResult)(ByVal source As IEnumerable) _
As IEnumerable(Of TResult)

    For Each obj As Object In source
        If TypeOf obj Is TResult Then
            Dim result As TResult = DirectCast(obj, TResult)
            Yield result
        End If
    Next

End Function



Here you can see the test is the same as the code that @CHill60 has posted, but as a generic test:
VB
If TypeOf obj Is TResult Then
    ' true result
End If

So, TResult is ComboBox and obj is the control in the form's Controls collection.
 
Share this answer
 
v3
Comments
CHill60 27-Jun-23 8:19am    
5'd. I really don't understand why the OP would not want to use this elegant solution
Graeme_Grant 27-Jun-23 8:23am    
Thanks. I do not understand either. I guess that generics scare some.
Appreciate the feedback, I think I solved the issue.

The code below allows me to loop through all combo boxes in the form and repeat the tasks. I am not sure why I could not get the For Each comboBox.... suggested to work but this appears to do the trick.

For Each cTrl As Control In Me.Controls
Dim cBox As System.Windows.Forms.ComboBox
cBox = cTrl
cBox.Name = cTrl.Name
cBox.Text = ""
Next
 
Share this answer
 
Comments
Graeme_Grant 26-Jun-23 12:40pm    
That code will throw a casting error if a control is not a ComboBox.

The code sample that I posted will filter by control type and only give you ComboBoxes.
Oh you're right, i left two lines out. The code does assume the names of the Comboboxes begin with "CB_" Thanks.

This is how if should read

For Each cTrl As Control In Me.Controls
if
Strings.Left(cTrl.Name, 3) = "CB_" Then
      Dim cBox As System.Windows.Forms.ComboBox
      cBox = cTrl
      cBox.Name = cTrl.Name
      cBox.Text = ""
   end if
Next
 
Share this answer
 
Comments
CHill60 27-Jun-23 8:18am    
You are far better off checking the type of the control as per Solution 1 than relying on a naming convention. What if down the line you forget that rule? Or your work goes to another developer who starts their combobox names with cmb and no underscore?
If you really don't want to use the rather elegant Solution 1 (why not?) then you can always test using
If TypeOf (cTrl) Is ComboBox Then ...
but Solution 1 is the correct way
Graeme_Grant 27-Jun-23 18:48pm    
+5 ... This is the old-school non-Linq way. I extracted the Microsoft implementation and converted it to VB to show the OP that what you propose is exactly what Microsoft is using internally in the OfType method! ;)
I'd love to use that solution but as previously mentioned, all attempts to try this give the following error.
Error BC31430 Expression of type 'Control' can never be of type 'VisualStyleElement.ComboBox'

It is on account of this that i came up with the method I did. I agree that the rule of remembering the naming configuration is a pain, if someone has a means of getting solution 1 to work, I am all ears.

I am baffled how my solution actually works but as it does, I'm using it.
 
Share this answer
 
Comments
CHill60 27-Jun-23 10:22am    
As an aside - if you want to reply to a comment use the "Reply" link next to it, if you want to comment on a post use the "Have a Question or Comment?" link next to the relevant post. It will be obvious to what you are responding and the poster will be informed of your response, but posting comments etc as a "Solution" will just confuse other readers and get you flamed.
You say you are baffled as to how it works - it will stop working when you hit a control that is not a combobox.
Regarding the issue - Graeme would not have see your error message as you commented on your own question instead of his solution, in the same way, readers will be confused as you what "Solution" 4 is referring

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900