Programmatically access controls on GroupBoxes tha

2019-09-21 05:28发布

问题:

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:

  1. I Placed the TabControl1 control from the VS 2010 toolbox on Form1.
  2. I created 19 TabPages on TabControl1
  3. On each TabPage I created multiple GroupBoxes for organization.
  4. Finally, I placed multiple controls like RadioButtons, TextBoxes, and Spinners in each of the GroupBoxes.
  5. 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.

回答1:

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 TextBoxes 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 CheckBoxes, 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 Controls inside parent, and all Controls 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 TextBoxes 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 TextBoxes 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.