vb.net Loop through Controls on Form and if ListView Loop through Columns and Rows - vb.net

I have 3 ListViews in a UserForm and also a few other items. Currently when I expand the UserForm, the ListViews and other items expand in relation to the increase in size of the UserForm.
What I'm after doing is also expanding the size of the Columns within the ListViews by cycling through all Controls on the UserForm and checking if it is a ListView, then cycling through all the columns and extending as required.
This is where I am currently at...
For Each Ctrl As Control In Me.Controls
If (TypeOf Ctrl Is ListView) Then
' This is where I'm not sure what to do!
' I want to loop through this Ctrl and view its columns
End If
Next
Anyone any ideas?

If Plutonix' suggestion of enabled auto-resizing columns doesn't work, then read on...
To access the control's properties, you'll need to cast it to ListView first (so far you've only checked to see if it is a ListView. Then, you can loop through the rows and columns:
For Each Ctrl As Control In Me.Controls
If TypeOf Ctrl Is ListView Then
Dim currentListView As ListView = DirectCast(Ctrl, ListView)
' Loop over the rows (items) in the view
For Each item As ListViewItem In currentListView.Items
Next
End If
Next
You might also end up needing a recursive control search -- your current loop will only look for controls that are a direct child of Me.
Another idea: simply return controls of the correct type in the outer for-loop:
For Each listViewControl As Control In Me.Controls.OfType(Of ListView)()
For Each item As ListViewItem In listViewControl.Items
Next
Next

Related

Getting reference to control from function

My application has a form which contains 4 tabs and each tab has a DataGridView (DGV) within it. There is also a panel of controls which sit outside of the tabs and are used for all the DGV controls.
I need to make sure that the code updates the correct DGV based on what the user is looking at. I currently do this for any events or functions where I need to do some work on a DGV:
Dim dgv As DataGridView = GetCurrentDGV(TabControl.SelectedTab)
For Each row As DataGridViewRow In dgv.SelectedRows
'Do work on row
Next
And this is the function GetCurrentDGV():
Private Function GetCurrentDGV(ByRef tab As TabPage) As DataGridView
For Each control As Control In tab.Controls
If control.GetType Is GetType(DataGridView) Then
Return CType(control, DataGridView)
End If
Next
End Function
There are a number of things I don't like about this.
Firstly, it is slow. I'm not exactly sure why as each tab only contains a DGV and nothing else (so the loop through controls is only a single item which should return on the first loop).
Secondly, there's a chance my function doesn't return anything which will give a null reference.
I am trying to avoid hard-coding the relationship between tabs and DGV but before I go down that route, are there better ways I could be doing this?

me.control.remove is removing every second control in a loop for some reason

I have some dynamically created checkboxes on my form and I want a function to delete them all.
I've got the following function:
Sub delete_checkboxes()
Dim radios = Controls.OfType(Of RadioButton).AsQueryable()
For Each r As RadioButton In radios
Me.Controls.Remove(r)
Next
End Sub
For some reason the above function only deletes every second radio button and leaves the rest.
Just as a test, I changed the function to delete radio buttons which are ticked:
Dim radios = Controls.OfType(Of RadioButton).AsQueryable()
For Each r As RadioButton In radios
If r.Checked Then
Me.Controls.Remove(r)
End If
Next
With the above I can tick each radio button and it will delete them invididually... so what it is in the first function which could be causing it to skip every second radio button?
Change AsQueryable() to ToList()
The reason it fails is that you are not supposed to modify a iterator while you are still looping over it. AsQueryable() is just using a state machine internally to know your current position in the Me.Controls collection. It doesn't actually keep it's own collection of controls, but just knows which controls you need from your original collection.
When you remove a control in the middle of loop, that position state is now wrong... in fact, it's off by one. You then remove the next control, which puts that internal position state off by one again, and so on. After a whole set of off-by-one adjustments and you end up with half of the controls still on your form.
ToList() will work, because it creates a separate collection for your controls, so that you don't have to mess with that state as your remove them from your Me.Controls collection.
this is usually how I accomplish it.
For Each cont As Control In Me.Controls
If cont.GetType().Name = "RadioButton" Then Me.Controls.Remove(cont)
Next

loop through all comboboxes with specific name

is it possible to loop through all comboboxes with specific name. For example I have 25 comboboxes in a groupbox i need to loop through 20 of them (each of this 20 have name special_combo_1,special_combo_2 and etc. but another 5 have another names so i need to leave as they are)and change their width at once or change the text or anything else.
You can use Control.Controls to get all the controls the GroupBox contains.
Then, you should cast each Control object to the ComboBox type by using TryCast(Object, Object).
You can check the prefix with String.StartsWith(String).
For Each Item As Control In GroupBox1.Controls
Dim ComboBoxItem As ComboBox = TryCast(Item, ComboBox)
If ComboBoxItem IsNot Nothing Then
If ComboBoxItem.Name.StartsWith("special_combo_") Then
' Code here
End If
End If
Next
Use the OfType to make a collection of comboboxes from the control collection. No TryCast needed so increase in preformance. Then filter them with the Where clause to drill it down even further. Now you iterate only a small collection of controls.
Dim spComboboxes =
GroupBox1.Controls.OfType(Of Combobox)().
Where(Function(cb) cb.Name.StartsWith("special_combo_")).ToList()
Iterate the comboboxes:
For Each cb In spComboboxes
'do something
Next

VB.Net Form DirectCast on Forms.Panel

I need to loop through the textboxes of my form, which are located inside a panel. I'm trying to do it like this....
For Each Cntrl As Control In DirectCast(Me.Controls(PanelName), Panel).Controls
next
The reason I need to feed the panel's name to the loop is because I have two panels that exist in 2 different TabPages. A button exists on each TabPage that performs the same function, but the panels and textboxes have different names. I have the loop inside a function that handles both TabPage button clicks, therefore I need the loop to point to the right panel.
The "PanelName" matches the target panel's name, and the panel is of System.Windows.Form.Panel.
I get the "Object reference not set to an instance of an object." message.
Is this not possible?
No need to cast:
For Each Cntrl As Control In PanelName.Controls
Next
If all you have is the name of the panel and not the control reference, then you at least need to know which TabPage has the panel:
For Each ctrl As Control In TabControl1.TabPages(1).Controls("panel1").Controls
Next
Alternatively, you can use:
Me.Controls.Find(PanelName, True)
to return the panel by name while searching child controls recursively.

how to clear all tools in the vb.net from

i have used many of the controls in vb.net forms, including a textbox and combobox, but I want to clear all my text boxes at once, while not typing textbox1.clear() for each one.
Is there any other way to clear all my textboxes?
If I understand you question right, you should be able to loop through all the controls on your form and check to see what Control type they are. Based on their type, either set the textbox Text property to String.Empty, or your ComboBox to the index of a blank ListItem (presumably item zero).
Something like:
For Each ctrl As Control In Me.Controls
If TypeOf ctrl Is TextBox Then
CType(ctrl, TextBox).Text = String.Empty
Else
' do something similar for your ComboBox
End If
Next
You can parse through each control on your form and test what type of control that is and handle each type separately, but it is easier to simply set each control manually.
Consider writing a ClearForm routine that does all of this, that way all you have to do is call the method.