How can you programmatically access controls on Tab Pages?
My code has many properties that I want to allow the user to initially set when the program starts. These properties will be used to define an Excel chart like title name, font colors, font size, chart position and size, X & Y series and many others properties. The program produces many charts each of which have their own set of properties. Each chart has the same set of properties but different values.
My solution using Form1 Designer:
- I Placed the TabControl1 control from the VS 2010 toolbox on Form1.
- I created 19 TabPages on TabControl1
- On each TabPage I created multiple GroupBoxes for organization.
- Finally, I placed multiple controls like RadioButtons, TextBoxes, and Spinners in each of the GroupBoxes.
- All of the above was done at design time.
Bad Example:
Dim TC1 As TabControl = TabControl1.TabPages.Item(1)
This is a bad example but I’m thinking I need to do something like this, i.e. before I can reach the actual user inputs via the RadioButtons, TextBoxes, or Spinners child controls I need to tell the complier the name of the TabControl1 and each TabPage contained in it. I’m not sure about each of the GroupBoxes that contain groups of RadioButtons and etc.
My Question: How do you programmatically access controls located on multiple GropBoxes located on each of the Tab Pages? I want to retrieve all the user input properties values on each of many TabPages and apply them when I create the Excel Charts.
A TabControl
is just a fancy way to organize controls on the same form. The point is that they are on the same form! You probably know that you use Me
to access the current form, then .ControlName
to access the control. Consider a TabControl
with two tabs and on each tab there is a TextBox
. These TextBox
es are on the same form, so you still need to use
Me.TextBox1.Text = "Text 1" ' the same as TextBox1.Text = "Text 1", but I like to be explicit
Me.TextBox2.Text = "Text 2"
This you already knew, as your problem stemmed from this behavior. However, there are some tricks to help you. Consider a TabControl
with two tabs, and on page 1 there is a control named tc1TextBox1
and on page 2 tc2TextBox1
. I'm using the prefix to distinguish between the pages. An additional TextBox
on page 1 would be named tc1TextBox2
etc., then say you wanted CheckBox
es, you could have tc1CheckBox1
and tc1CheckBox2
etc. The way I would access them is with LINQ
Define an extension method in a module
Imports System.Runtime.CompilerServices
Public Module ExtensionMethods
<Extension()> _
Public Function ChildControls(Of T As Control)(ByVal parent As Control) As List(Of T)
Dim result As New List(Of Control)
For Each ctrl As Control In parent.Controls
If TypeOf ctrl Is T Then result.Add(ctrl)
result.AddRange(ctrl.ChildControls(Of T)())
Next
Return result.ToArray().Select(Of T)(Function(arg1) CType(arg1, T)).ToList()
End Function
End Module
This method returns you all the Control
s inside parent
, and all Control
s inside those, and so on, recursively. It also gives you an IEnumerable
List(Of Control)
in contrast to Control.Controls()
which is not IEnumerable
and only returns controls in the control, not in its containers.
Using LINQ, you can filter the results of ChildControls
by Type
or Name
. For instance, the code
Dim textBoxes = Me.ChildControls(Of TextBox)()
returns all the TextBox
es in Me. Let's take it a step further:
Dim textBoxes = Me.ChildControls(Of TextBox)().Where(Function(tb) tb.Name.StartsWith("tc1"))
returns all the TextBox
es with the prefix "tc1". So you see you can set up the controls on your form to better group them at runtime. Here's an idea specific for Excel sheets
Dim xlBook As Excel.Workbook
For i As Integer = 1 To 20
Dim nameString = "txtSheetName" & i.ToString() ' TextBoxes named txtSheetName1, txtSheetName2, etc.
xlBook.Sheets(i).Name = Me.ChildControls(Of TextBox)().Where(Function(tb) tb.Name = nameString).First().Text
Dim enabledString = "chkEnabled" & i.ToString() ' CheckBoxes named chkEnabled1, chkEnabled2, etc.
xlBook.Sheets(i).Enabled = Me.ChildControls(Of CheckBox)().Where(Function(tb) tb.Name = enabledString).First().Checked
'etc.
Next
which will loop over your tab control indices, and set properties for each corresponding excel sheet. This code should give you a good idea of a direction you can take.