accessing multiple form controls using a variable for the name

末鹿安然 提交于 2019-12-11 03:22:39

问题


I'm trying to iterate through a group of ComboBoxes and set a property using a concatenated string & variable to represent the name of the control. However, I can't get the instance of the form to recognize the (String & Integer_Variable) as one of its controls -- and so it doesn't recognize any of the appropriate properties or subroutines as members of the System.Windows.Forms.Control.

I found the DirectCast solution on SO and it appears to work (although I'm dubious), but that feels like a very clumsy solution. Is there a cleaner way to do this?

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

This code was originally VBA / VB6, which I put through ArtinSoft's Visual Basic Upgrade Companion (VBUC). FWIW, I'm using Microsoft Visual Basic 2010 Express.


回答1:


To answer your questions:

  1. ComboBox1.SelectedIndex works because ComboBox1 is the control that is present in the Form's ControlCollection
  2. Me.ComboBoxPrinter1.SelectedIndex works because Me is a reference to your Form class an it is referencing the Control.
  3. Me.("ComboBoxPrinter" & myTempCount).SelectedIndex doesn't work because the string ComboBoxPrinter & myTempCount is a string not a Control.
  4. Me.Controls.("ComboBoxPrinter" & myTempCount).SelectedIndex doesn't work for the same reasons.
  5. The other two instances work because you are using the string as a key to lookup and return the control which you the cast to the proper type and set your property.

I personally usually use CType other than DirectCast. The main difference according to this link between CType and DirectCast is that DirectCast has to be the exact Type where as CType can be used in narrowing or widening Conversions. DirectCast is more effiecent albeit more finicky.

That being said you could do something like this:

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

I am not using Me in front of Controls since it refers to the same collection, if your controls are in another collection you will need to use that Container instead. i.e. if you were using a Panel Panel1.Controls.ContainsKey




回答2:


Ouch!!! I messed with Direct Cast once. I remember it being a nightmare. My preference is to either stick with server side controls, or write them in as client side Javascript/Ajax. Where at in your above code is it failing? Any inner exceptions?




回答3:


Maybe you can try something like this (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]
}

Here is the above code converted to VB.NET using online tool:

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

I hope this helps!




回答4:


I came across this issue again with multiple controls of differing types that needed the same operation performed on a common property (like .Text). Since you cannot use a variable to represent the control type parameter in CType(), you'll have to use a conditional and a corresponding hardcoded CType() command to get the control. This is what I came up with:

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 is the concatenated string name. So, you can use this Function pretty much the same way the previous answers used CType():

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



回答5:


Something like this:

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


来源:https://stackoverflow.com/questions/10711844/accessing-multiple-form-controls-using-a-variable-for-the-name

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!