VB.NET перебирает элементы управления формой с одинаковыми именами

Хорошо, у меня есть щекотка для ваших мозгов. Я конвертирую программу, написанную на VB6, в Visual Studio 2010 VB.Net и столкнулся с проблемой. Я пытаюсь перебрать 20 элементов формы в форме, все из которых имеют префикс «chkCustomerItems», а затем имеют число от 1 до 20 за ними. Я использую это с поиском в базе данных, так что если есть запись в базе данных, она затем применяет имя элемента базы данных к текстовому полю флажка и включает видимость. Вот код, который я написал: ConnOpenClose()

Rs = New ADODB.Recordset
Sql = "SELECT * FROM CustomersItems;"
Rs.Open(Sql, Conn)

If Rs.EOF = False Then
    tempInteger = 1
    Rs.MoveFirst()
    Do
        tempString = "chkCustomerItems" & tempInteger.ToString
        Me.Controls(tempString).Text = Rs.Fields("Item").Value
        Me.Controls(tempString).Visible = True
        tempInteger = tempInteger + 1
        Rs.MoveNext()
        If tempInteger = 21 Then GoTo ExitLoop
    Loop Until Rs.EOF
ExitLoop:
End If

Когда он запускается, я получаю ошибку NullReferenceException. Это в основном код, который я использовал в VB6 (с некоторыми изменениями для инфраструктуры .NET). Помогите мне, пожалуйста, понять, что я делаю неправильно, на данный момент мне приходится жестко кодировать все 20 элементов, и хотя это работает, это не выглядит и не работает красиво.

заранее спасибо


person Russell    schedule 02.01.2012    source источник


Ответы (2)


вы используете свойство Text, поэтому я предполагаю, что это текстовое поле.
попробуйте это:

DirectCast(Controls(tempString), TextBox).Text = Rs.Fields("Item").Value
person John Woo    schedule 02.01.2012
comment
ВАУ, это именно то, что я искал!! Огромное спасибо. Я знал, что в .NET есть код, который делает то, что я хочу. - person Russell; 02.01.2012

Если какие-либо из ваших элементов управления встроены в какие-либо элементы управления-контейнеры (панели, вкладки и т. д.), вы не сможете получить к ним доступ через индексирование коллекции элементов управления.

Вместо этого вам нужно будет использовать Controls.Find со вторым параметром (searchAllChildren), установленным в true (я также добавил некоторые дополнительные проверки и способы выполнения действий .Net):

 Do
    tempString = "chkCustomerItems" & tempInteger.ToString

    Dim aoControls As Control()
    aoControls = Me.Controls.Find(tempString, True)
    If aoControls IsNot Nothing AndAlso aoControls.Length <> 0 Then
       Dim oTextBox As TextBox

       oTextBox = TryCast(aoControls(0), TextBox)
       If oTextBox IsNot Nothing Then
          oTextBox.Text = Rs.Fields("Item").Value
          oTextBox.Visible = True
       End If
    End If

    tempInteger = tempInteger + 1
    Rs.MoveNext()
    If tempInteger = 21 Then 
       Exit Do
    End If
Loop Until Rs.EOF
person competent_tech    schedule 02.01.2012
comment
Я помещаю этот код точно так, как вы его набрали, однако в строке oTextBox = TryCast(aoControls, TextBox) я получаю сообщение об ошибке Значение типа «1-мерный массив System.Windows.Form.Control» не может быть преобразован в «Ssytem.Windows.Forms.Textbox» в aoControls. - Есть идеи, почему? - person Russell; 02.01.2012
comment
О, извините за это. Должно быть aoControls(0). Я обновил ответ. - person competent_tech; 02.01.2012