2012-05-23 3 views
1

Я пытаюсь выполнить итерацию по группе ComboBoxes и установить свойство с помощью конкатенированной строки & переменной для представления имени элемента управления. Однако я не могу получить экземпляр формы для распознавания (String Integer_Variable) в качестве одного из своих элементов управления - и поэтому он не распознает какие-либо из соответствующих свойств или подпрограмм как члены System.Windows.Forms .Control.Доступ к нескольким элементам управления формы с использованием переменной для имени

Я нашел DirectCast solution on SO и, похоже, работает (хотя я сомневаюсь), но это похоже на очень неуклюжие решения. Есть ли более чистый способ сделать это?

For myTempCount = 1 To 6 
    If tempValue < Me.("ComboBox" & myTempCount).Items.Count Then 
     ComboBox.SelectedIndex = tempValue 'appears to work -- how? 
     Me.ComboBox.SelectedIndex = tempValue 'appears to work 

     Me.("ComboBox" & myTempCount).SelectedIndex = tempValue 'doesn't work 
     Me.Controls.("ComboBox" & myTempCount).SelectedIndex = tempValue 'doesn't work 

     DirectCast(Me.Controls.Find(("ComboBox" & myTempCount), True)(0), ComboBox).SelectedIndex = tempValue 'appears to work 
     DirectCast(Me.Controls("ComboBox" & myTempCount), ComboBox).SelectedIndex = tempValue 'appears to work 
Next 

Этот код был первоначально VBA/VB6, который я положил через Basic Companion ArtinSoft в визуальном обновлении (VBUC). FWIW, я использую Microsoft Visual Basic 2010 Express.

ответ

2

Чтобы ответить на ваши вопросы:

  1. ComboBox1.SelectedIndex работает, потому что ComboBox1 является контроль, который присутствует в ControlCollection форме в
  2. Me.ComboBoxPrinter1.SelectedIndex работает, потому что мне это ссылка на ваш класс Сформировать он ссылается на управление.
  3. Me.("ComboBoxPrinter" & myTempCount).SelectedIndex не работает, потому что строка ComboBoxPrinter & myTempCount является строкой, а не элементом управления.
  4. Me.Controls.("ComboBoxPrinter" & myTempCount).SelectedIndex не работает по тем же причинам.
  5. Другие два экземпляра работают, потому что вы используете строку в качестве ключа для поиска и возвращаете элемент управления, который вы передали, в соответствующий тип и задаете свое свойство.

Я лично обычно использую CType, кроме DirectCast. Основное различие в соответствии с этим link между CType и DirectCast заключается в том, что DirectCast должен быть точным типом, где CType может использоваться для сужения или расширения преобразований. DirectCast более эффективен, хотя и более утончен.

Это сказанное вы могли бы сделать что-то вроде этого:

For myTempCount = 1 To 6 
    If Controls.ContainsKey("ComboBox" & myTempCount) Then 
     CType(Controls("ComboBox" & myTempCount), ComboBox).SelectedIndex = tempValue 
    End If 
Next 

Я не использую меня перед Controls, так как он относится к той же коллекции, если ваши средства управления находятся в другой коллекции вам нужно будет использовать это Контейнер. т. е. если вы использовали панель Panel1.Controls.ContainsKey

+0

Спасибо, это было очень полезно - особенно предупреждение о DirectCast! Я должен был понять, что мне нужно было передать String как Control. – Wingman4l7

0

Ouch !!! Однажды я испортил Direct Cast. Я помню, что это был кошмар. Мое предпочтение - либо придерживаться серверных элементов управления, либо записывать их в качестве клиентской стороны Javascript/Ajax. Где в вашем вышеуказанном коде это не удается? Любые внутренние исключения?

+0

Жаль, что вы видели, что он не должен был быть в той форме, , Я случайно отправил сообщение, пока я еще составлял вопрос. =) – Wingman4l7

0

Может быть, вы можете попробовать что-то вроде этого (C#):

List<Control> comboBoxes = new List<Control> 
{ 
    ComboBoxPrinter1, 
    ComboBoxPrinter2, 
    ComboBoxPrinter3, 
    ComboBoxPrinter4, 
    ComboBoxPrinter5, 
    ComboBoxPrinter6 
}; 

// loop through combo boxes collection by position 
for (int = 0; i < comboBoxes.Length;i++) 
{ 
    // put in your if logic here, and refer to current combo box using comboBoxes[i] 
} 

Вот приведенный выше код преобразуется в VB.NET с помощью онлайн-инструмент:

 
Dim comboBoxes As New List(Of Control)() From { _ 
    ComboBoxPrinter1, _ 
    ComboBoxPrinter2, _ 
    ComboBoxPrinter3, _ 
    ComboBoxPrinter4, _ 
    ComboBoxPrinter5, _ 
    ComboBoxPrinter6 _ 
} 

For i As Integer = 0 To comboBoxes.Count - 1 
    // you can hook in your if logic and refer to each combo box using comboBoxes[i] 
Next 

Я надеюсь, что это помогает!

+0

Это сработает, но я пытаюсь избежать перечисления имен полного управления где-то, так как эта итерация происходит в другом месте кода. – Wingman4l7

+0

У меня было ощущение, что вы скажете это :) В этом случае я бы извлек эту строку, которая определяет список элементов управления в свой собственный метод, поэтому вы можете использовать его из нескольких мест. Надеюсь, вы найдете это несколько изящным способом уменьшить дублирование и упростить поддержку кода :) – dplante

0

Я снова столкнулся с этой проблемой с несколькими элементами управления различного типа, которые нуждались в той же операции, выполняемой с общим свойством (например, .Text).Поскольку вы не можете использовать переменную для представления параметра типа управления в CType(), вам нужно будет использовать условную и соответствующую команду hardcoded CType() для получения элемента управления. Это то, что я придумал:

Function getControl(ByVal controlName As String) As Control 
    numCtrls = FrameMain.Controls.Count() 
    For I As Integer = 0 To numCtrls - 1 
     If FrameMain.Controls.Item(I).Name = controlName Then 
      If TypeOf FrameMain.Controls.Item(I) Is ComboBox Then 
       Return CType(FrameMain.Controls(controlName), ComboBox) 
      End If 
     End If 
    Next 
End Function 

controlName является каскадный строка имени. Таким образом, вы можете использовать эту функцию в значительной степени так же, как предыдущие ответы используется CType():

getControl("TextBox" & myTempCount).Text = "whatever" 
0

Что-то вроде этого:

Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click 
    Dim control As Control = Me.Controls("Button1") 
    Select Case control.GetType 
     Case GetType(Button) 
      Dim btn As Button = DirectCast(control, Button) 
      With btn 
       .Text = "hi" 
      End With 
     Case GetType(Label) 
      Dim lbl As Label = DirectCast(control, Label) 
      With lbl 
       .Text = "hi" 
      End With 
     Case Else 'etc 
    End Select 
End Sub