【问题标题】:Create and loop through collection subset of controls创建并循环通过控件的集合子集
【发布时间】:2015-01-04 09:25:48
【问题描述】:

我正在制作一个小的 vb.net windows 窗体应用程序,其中有 4 个 ComboBoxes。我想将 ComboBoxes 添加到一个集合中,并能够遍历该集合以引用每个集合。

表单上还有其他 ComboBox,所以我不能只将集合用于整个表单(无法更改表单布局,例如添加容器等)。

我的想法是这样的:

Public Class Form1
    Dim IoTypeCombos As New ControlCollection(Me) From {Me.IO1_ComboBox, Me.IO2_ComboBox, Me.IO3_ComboBox, Me.IO4_ComboBox}
    Dim IoTypes As New Collection() From {"Out 0", "Out 1", "Input", "Analog"}

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        For Each cb As combobox In Me.IoTypeCombos
            FillComboBox(cb, Types)
        Next
    End Sub

    Function FillComboBox(cb As Control, cc As Collection) As Boolean
        Dim cbc As ComboBox = CType(cb, ComboBox)
        If cc.Count = 0 Then
            Return False
        End If
        For Each cn In cc
            cbc.Items.Add(cn)
       Next
       Return True
    End Function

这不会引发任何异常,但它也不会填充 ComboBoxes :( 如果我将单个控件传递给 FillComboBox(),则它可以完美地工作。 我究竟做错了什么?谢谢

【问题讨论】:

    标签: vb.net collections combobox controlcollection


    【解决方案1】:

    这行是非法的:

    Public Class Form1
        Dim IoTypeCombos As New ControlCollection(Me) From {Me.IO1_ComboBox, 
                    Me.IO2_ComboBox, Me.IO3_ComboBox, Me.IO4_ComboBox }
    

    该代码将在构造函数之前运行,在 MeION_ComboBox 存在之前。在这种情况下,结果集合不包含任何内容,因为还没有任何东西可以放入其中。

    在其他情况下,在控件存在之前引用它们可能会导致NullReference 被抛出,但由于一个奇怪的错误,它可能不会被报告。发生这种情况时,将跳过其余代码并简单地显示表单。

    在任何一种情况下,解决方案都是在表单级别声明您的集合,但一旦控件确实存在,就在表单加载事件中填充它。我也会使用 Collection(Of T) 代替(数组或 List(Of T) 也可以,但 OP 使用/询问集合):

    Imports System.Collections.ObjectModel
    
    Public Class Form1
         Dim IoTypeCombos As Collection(Of ComboBox)  ' form and controls Do No Exist yet
    
         Public Sub New
             '...
             InitializeComponent()
            ' NOW they exist
         End Sub
    
         Sub Form_Load
             IoTypeCombos = New Collection(Of ComboBox)
             IoTypeCombos.Add(IO1_ComboBox)
             IoTypeCombos.Add(IO2_ComboBox) 
             ...    
    

    如果你使用List(Of ComboBox),你可以用不同的方式填充它:

     ' in the ctor:
     IoTypeCombos = New List(Of ComboBox)({IO1_ComboBox, IO2_ComboBox...})
     ' using AddRange:
     IoTypeCombos.AddRange({IO1_ComboBox, IO2_ComboBox...})
    

    【讨论】:

    • 我收到Dim IotypeCombos As Collection(Of ComboBox) 的错误“Microsoft.VisualBasic.Collection 没有类型参数,因此不能有类型参数”...
    • 你对我的 OP 的评论导致我使用 Dim IoTypeCombos() As ComboBox 而不是 IoTypeCombos = New ComboBox() {Me.IO1_ComboBox, Me.IO2_ComboBox, Me.IO3_ComboBox, Me.IO4_ComboBox} For Each cb As ComboBox In Me.IoTypeCombos 这可以解决问题
    • 你需要添加对System.Collections.ObjectModel的引用,并如图所示导入;简单地在同一个地方使用一个数组也不起作用——它们的控件还不存在
    • 问题出在ControlCollection 类Add 方法中的这一行:if(value == null) return; 其中value 是要添加到集合中的控件。所以在 InitializeComponent 之前调用它会导致一个空集合。
    • @steve,正确。当控件引用在 InitializeComponent 之前起作用和不起作用时,这有点令人困惑。以为我已经弄清楚了……修改后的答案。
    【解决方案2】:

    不确定您是否需要 where 子句,但如果您有其他组合框没有这样的名称并且不希望它们出现在集合中,那么您确实需要它。

    Dim IoTypeComboboxes = 
        Me.Controls.OfType(Of Combobox)().Where(Function(cb) cb.Name.StartsWith("IO")).ToList()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-11
      • 2012-03-19
      • 2020-04-03
      • 2018-06-20
      相关资源
      最近更新 更多