none
Using a Variable for a control name works unless the control is in a panel or a tab. RRS feed

  • Question

  • This code works just fine on a form

            Dim x As Integer = 1
            For x = 1 To 3
                Dim TextBoxName As TextBox = Controls("txtCvar" & x)
                TextBoxName.Text = "This Works"
            Next

    If I put the textboxes in a Panel or a Tab, I get errors...

    System.NullReferenceException: 'Object reference not set to an instance of an object.'
    TextBoxName was Nothing.

    Any Ideas on how to correct that?


    Friday, March 27, 2020 6:26 PM

All replies

  • Not so strange because the controls are not anymore on the form but in the panel. 

    therefore it becomes 

        Dim x As Integer = 1
            For x = 1 To 3
                Dim TextBoxName As TextBox = Panel1.Controls("txtCvar" & x)
                TextBoxName.Text = "This Works"
            Next

    I did not test it, I did not even know the controls could currently be addressed direct by a symbolic name. But my code fulfils the principle. 

    I see now, you have to set for this code Option Strict to off which a self respecting programmer doesn't do. 

    But the code should fit. 


    Success
    Cor


    Friday, March 27, 2020 7:09 PM
  • This code works just fine on a form

            Dim x As Integer = 1
            For x = 1 To 3
                Dim TextBoxName As TextBox = Controls("txtCvar" & x)
                TextBoxName.Text = "This Works"
            Next

    If I put the textboxes in a Panel or a Tab, I get errors...

    System.NullReferenceException: 'Object reference not set to an instance of an object.'
    TextBoxName was Nothing.

    Any Ideas on how to correct that?


    Hi

    You question is encoded - I don't know how to decode!

    Here is some code that shows you how to put some TextBoxes on a Form and in a Panel.

    This example needs a new Form1 with Panel1 on it, Also shows attaching a Handler for all of them.

    ' Form1 with Panel1
    Option Strict On
    Option Explicit On
    Public Class Form1
      Dim WithEvents TB As New TextBox
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    
        ' add TB to Form
        Dim x As Integer = 10
        Dim y As Integer = 10
        For i As Integer = 1 To 3
          Dim ntb As New TextBox
          With ntb
            .Name = "FormTBName" & i.ToString
            .Text = "TextBox " & i.ToString
            .Location = New Point(x, y)
            y += 33
          End With
          Controls.Add(ntb)
          AddHandler ntb.Click, AddressOf Button_Click
        Next
    
        ' add TB to Panel
        x = 3
        y = 3
        For i As Integer = 11 To 13
          Dim ntb As New TextBox
          With ntb
            .Name = "PanelTBName" & i.ToString
            .Text = "TextBox " & i.ToString
            .Location = New Point(x, y)
            y += 33
          End With
          Panel1.Controls.Add(ntb)
          AddHandler ntb.Click, AddressOf Button_Click
        Next
      End Sub
      Private Sub Button_Click(sender As Object, e As EventArgs)
        Dim tb As TextBox = DirectCast(sender, TextBox)
        MessageBox.Show("You clicked TB " & tb.Name)
      End Sub
    End Class


    Regards Les, Livingston, Scotland



    • Edited by leshay Friday, March 27, 2020 9:45 PM
    Friday, March 27, 2020 7:19 PM
  • Hello,

    This is a proof of concept. The following code works off a base language extension called Descendants which expects a control type e.g. TextBox called as if it's a method of a parent control.

    For instance, I have a form with a panel and have a TextBox on the form and three TextBox on a panel, the following line would return 4 TextBoxes

    Dim TextBoxesOnAllControls = Descendants(Of TextBox)

    If I only want the TextBox controls on the Panel which means this returns just three TextBoxes

    Dim textBoxs = Panel1.Descendants(Of TextBox)

    I've created extension methods off the base extension e.g. get textBoxes on the panel.

    Dim textBoxs = Panel1.TextBoxList()


    Complete example for you:

    Public Class Form1
        Private Sub SetValuesButton_Click(sender As Object, e As EventArgs) _
            Handles SetValuesButton.Click
    
            Dim textBoxs = Panel1.TextBoxList().OrderBy(Function(tb) tb.Name)
    
            For index As Integer = 0 To textBoxs.Count - 1
                textBoxs(index).Text = $"Number {index + 1}"
            Next
        End Sub
    End Class

    Extension methods:

    Imports System.Runtime.CompilerServices
    
    Public Module ControlExtensions
        <Extension>
        Public Iterator Function Descendants(Of T As Class)(control As Control) As IEnumerable(Of T)
            For Each child As Control In control.Controls
    
                Dim currentChild = TryCast(child, T)
                If currentChild IsNot Nothing Then
                    Yield currentChild
                End If
    
                If child.HasChildren Then
                    For Each descendant As T In child.Descendants(Of T)()
                        Yield descendant
                    Next
                End If
            Next
    
        End Function
        <Extension>
        Public Function TextBoxList(pControl As Control) As List(Of TextBox)
            Return pControl.Descendants(Of TextBox)().ToList()
        End Function
    End Module

    Full source for extensions on GitHub

    https://github.com/karenpayneoregon/DescendantsVisalBasicWinForms/blob/master/DescendantsLibrary/ControlExtensions.vb

    In closing, this might seem (the extension methods) like a lot of code, that is a perspective when not realizing these extensions can be used anyplace in any project.


    Please remember to mark the replies as answers if they help and unmarked them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my Twitter (Karen Payne) or Facebook (Karen Payne) via my MSDN profile but will not answer coding question on either.

    NuGet BaseConnectionLibrary for database connections.

    StackOverFlow
    profile for Karen Payne on Stack Exchange

    Friday, March 27, 2020 8:44 PM
    Moderator
  • This should work too, even if you have nested panels:

    Dim TextBoxName As TextBox = CType(Controls.Find("txtCvar" & x, searchAllChildren:=True)(0), TextBox)

    Saturday, March 28, 2020 8:45 AM