Set a group of controls visible with one line of code? - vb.net

Is it possible to clump a group of controls together and be able to set it visible with one line rather than having to do each individual control's .visible property? I know it doesn't hurt anything but would like to keep it looking neat and not clump up a function with a page full of .visible control calls.

Just group your controls in a List(Of Control) or an array and set the Visible property using either the ForEach-method or a simple For Each-loop.
e.g.:
Dim toToggle = {OkButton, CancelButton, ControlPanel, SelectionComboBox}
For Each ctrl in toToggle
ctrl.Visible = False
Next
or
Dim toToggle = {OkButton, CancelButton, ControlPanel}.ToList()
toToggle.ForEach(Sub(c) c.Visible = False)

I like Dominic's solution. Another approach (and this depends on how your Winform is laid out) would be to group the controls into a panel:
For Each ctrl as Control in MyPanel.Controls
c.Visible = False
Next
Really all this approach does is keeps you from having to create a new list, but maybe that would be better so you can choose precisely which controls to add.

Related

How does Tab Index work if the control's enabled property is false

If I'm viewing a form and I set the enabled property of the control with tab index = 0, does the cursor then move to the next tab index? Do I need to, and is there a way, to force the tab to set to the first control with Enabled = True?
So in order to achieve this (assuming there are no panels on your form), this is how you could iterate through the controls in tab order. The first control which you encounter and which is enabled, you set the focus on it and leave the Sub. The myFirstControl variable is initialized by you with the first control in the tab order list of the form.
Private Sub IterateControls()
Dim ctrl As Control = myFirstControl
While ctrl IsNot Nothing
If ctrl.Enabled = True Then
Me.ActiveControl = ctrl
Exit Sub
End If
ctrl = Me.GetNextControl(ctrl, True)
End While
End Sub
If you have panels also, you should build a dictionary of panels (with the panel as key, its first control as value) and take them one by one using a For loop. The For loop should be placed to include the whole method's code, but this time you initiate the ctrl variable with the first control from the panel (i.e. the value of the current dictionary entry), instead of the first control of the Form, and also you would call myPanel.GetNextControl(...) instead of Me.GetNextControl(...). The other code lines should remain the same. If this is not helpful enough, add a comment and I will edit my answer.

How to Use For Each cnt Loop to Target Specific Tags on Controls

I'm making a form that has a few hundred labels, and when a Clear button is clicked, I need to reset the text of specific labels to 0 while leaving other label's text alone. I don't want to use a group box because it will not look good with my current layout.
I'm trying to use the code:
For Each cnt In Me.Controls
If TypeOf cnt Is Label Then
CType(cnt, Label).Text = ""
End If
Which works fine for clearing every Label, but I want to specify a specific Tag as well. I tried
For Each cnt In Me.Controls
If TypeOf cnt Is Label And CType(cnt, Label).Tag = "ResetTo0" Then
CType(cnt, Label).Text = ""
End If
When I try to use this code, I get a cast exception error.
Does anyone know how I can add in my tag as well without getting a cast error, or a better way to do this?
Just use the extension OfType to get only labels and already of the right type
For Each cnt In Me.Controls.OfType(Of Label)
If cnt.Tag = "ResetTo0" Then
cnt.Text = ""
End If
Next
And if not all labels have the Tag property set then add also a check for Nothing
if cnt.Tag IsNot Nothing AndAlso cnt.Tag = "ResetTo0" Then
.....
End if
You can even try with a single line (albeit I suspect that this approach is not the best for clarity and performance)
Me.Controls.OfType(Of Label).
Where(Function(x) x.Tag = "ResetTo0").
ToList().
ForEach(Function(k) k.Text = "")

Changing the alignment of dynamic labels

I have made a program that deals with labels' text alignment.
I have used:
Dim con7 As Control
For Each con7 In Me.Controls
con7.TextAlign = 'whatever is needed
Next
But the problem is the TextAlign part. The problem that arises is that TextAlign is not a property of all controls. What is the best way to fix this?
You're trying to assign each child control to a variable of type Label but, as the error message indicates, you clearly have at least one control that is not a Label. There are a couple of ways you can handle that but the simplest is to use Me.Controls.OfType(Of Label)(), which will filter out all but Label controls.
You don't need the following code:
Dim con7 As Control
con7 is declared within the loop.
Since you only want to loop through labels use the following code:
For Each lbl In Me.Controls.OfType(Of Label)()
lbl.TextAlign = ...
Next

Set the order in which form controls are looped through

I'm looping through all of the controls on a certain Tab Page and the grabbing the .tag property for some further actions from checkboxes that are checked.
However, I require these controls to be looped in a certain order (I was hoping they'd be ordered by tab index), but it appears that they are not.
Is there any way to force the order that they are looped? Thanks.
Dim objCtrl As Control
For Each objCtrl In Me.objConfigForm.tabPageGeneral.Controls
If TypeOf objCtrl Is CheckBox AndAlso DirectCast(objCtrl, CheckBox).Checked Then
Dim strProp As String = DirectCast(objCtrl, CheckBox).Tag
Dim strListItem As String = CallByName(objUser, strProp, CallType.Get)
lstGeneral.Add(strListItem)
End If
Next
Use LINQ to sort the controls by TabIndex, like this:
For Each objCtrl As Control In Me.Controls.Cast(Of Control).OrderBy(Function(c) c.TabIndex)
If TypeOf objCtrl Is CheckBox AndAlso DirectCast(objCtrl, CheckBox).Checked Then
Dim strProp As String = DirectCast(objCtrl, CheckBox).Tag
Dim strListItem As String = CallByName(objUser, strProp, CallType.Get)
lstGeneral.Add(strListItem)
End If
Next
Note: The above code requires the System.Linq namespace be imported into your code file to support the Cast() and OrderBy() LINQ extension methods.
Use the .OrderBy() extension to choose an order. Also, while we're at it, you can replace the If block with Where() and OfType() extensions to reduce nesting and casting:
For Each box As CheckBox In Me.Controls.OfType(Of CheckBox)() _
.Where(Function(b) b.Checked) _
.OrderBy(Function(b) b.TabIndex)
lstGeneral.Add(CallByName(objUser, box.Tag, CallType.Get))
Next
Update: this is a bit old, but it came back into my feed today, so it's still indexed by Google somewhere. With that in mind, today I'd write the code like this instead:
Dim selectedCheckboxNames = Me.Controls.
OfType(Of CheckBox)().
Where(Function(b) b.Checked).
OrderBy(Function(b) b.TabIndex).
Select(Function(b) CallByName(objUser, b.Tag, CallType.Get))
lstGeneral.AddRange(selectedCheckboxNames)
One of the important change is introducing a variable for the result of the linq query. This can sometimes add valuable insight to code for future developers, and it always helps make the For Each loop easier to read... assuming you haven't also been able to convert to an AddRange(), as I've done here. I'm also more comfortable now taking advantage of implicit line continuations and Option Infer.

Form control within Groupbox control

I have multiple form application in vb.net
Now i rose to a condition where i want to display one Form in the Groupbox/Panel control of other form.
Is there any way to achieve that???
Any help is appreciated..
If you must, you can do that. Here is an example:
Dim f As New Form
f.TopLevel = False
f.FormBorderStyle = FormBorderStyle.None
f.Dock = DockStyle.Fill
f.Visible = True
Panel1.Controls.Add(f)
The TopLevel = False is a requirement. Setting the FormBorderStyle and Dock style are optional, but probably what you are looking to do.
You cannot put Form on another Form - use User Control for that.
see
User Control vs. Windows Form