VB.NET - 遍历容器对象中的控件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/199521/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 13:50:42  来源:igfitidea点击:

VB.NET - Iterating through controls in a container object

vb.net

提问by JosephStyons

I have a form with a "Clear" button.

我有一个带有“清除”按钮的表单。

When the user clicks "Clear", I want to clear the value of all the visible elements on the form. In the case of date controls, I want to reset them to the current date.

当用户单击“清除”时,我想清除表单上所有可见元素的值。在日期控件的情况下,我想将它们重置为当前日期。

All of my controls are contained on a Panel.

我所有的控件都包含在一个面板上。

Right now, I'm doing this with the below code. Is there an easier way than manually checking for each control type? This method seems excessively unwieldy.

现在,我正在使用以下代码执行此操作。有没有比手动检查每种控件类型更简单的方法?这种方法似乎过于笨拙。

To make matters worse, in order to recursively clear controls inside sub-containers (i.e., a group box within the panel) I have to repeat the whole monster with an overloaded "GroupBox" version.

更糟糕的是,为了递归地清除子容器内的控件(即面板中的组框),我必须用重载的“GroupBox”版本重复整个怪物。

Edit: Thanks to your suggestions, the below code is greatly simplified.

编辑:感谢您的建议,以下代码已大大简化。

Private Sub btnClear_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnClear.Click
    'User clicks Clear, so clear all the controls within this panel
    ClearAllControls(panMid, True) 'True indicates that yes, i want to recurse through sub-containers
End Sub

ClearAllControls(ByRef container As Panel, Optional Recurse As Boolean = True)   
  'Clear all of the controls within the container object
  'If "Recurse" is true, then also clear controls within any sub-containers
  Dim ctrl As Control
  For Each ctrl In container.Controls
      If (ctrl.GetType() Is GetType(TextBox)) Then
          Dim txt As TextBox = CType(ctrl, TextBox)
          txt.Text = ""
      End If
      If (ctrl.GetType() Is GetType(CheckBox)) Then
          Dim chkbx As CheckBox = CType(ctrl, CheckBox)
          chkbx.Checked = False
      End If
      If (ctrl.GetType() Is GetType(ComboBox)) Then
          Dim cbobx As ComboBox = CType(ctrl, ComboBox)
          cbobx.SelectedIndex = -1
      End If
      If (ctrl.GetType() Is GetType(DateTimePicker)) Then
          Dim dtp As DateTimePicker = CType(ctrl, DateTimePicker)
          dtp.Value = Now()
      End If

      If Recurse Then
          If (ctrl.GetType() Is GetType(Panel)) Then
              Dim pnl As Panel = CType(ctrl, Panel)
              ClearAllControls(pnl, Recurse)
          End If
          If ctrl.GetType() Is GetType(GroupBox) Then
              Dim grbx As GroupBox = CType(ctrl, GroupBox)
              ClearAllControls(grbx, Recurse)
          End If
      End If
  Next
End Sub

@Theraccoonbear: I like your suggestion, but when I change the declaration to this:

@Theraccoonbear:我喜欢你的建议,但是当我将声明更改为:

Private Sub ClearAllControls(ByRef controls As ControlCollection, Optional ByVal Recurse As Boolean = True)

Then this line gives me "Unable to cast object of type 'ControlCollection' to type 'ControlCollection'.":

然后这一行给了我“无法将'ControlCollection'类型的对象转换为'ControlCollection'类型。”:

  ClearAllControls(panMid.Controls)

采纳答案by Mark Brackett

You can skip the GetType and CType dance with TryCast:

您可以使用TryCast跳过 GetType 和 CType 舞蹈:

Dim dtp as DateTimePicker = TryCast(ctrl, DateTimePicker)
If dtp IsNot Nothing then dtp.Value = Now()

That'll save you about 10 lines.

这将为您节省大约 10 行。

An extension methodoff the Control class should keep it pretty tidy:

Control 类的扩展方法应该让它保持整洁:

<Extension()> _
Public Shared Sub ClearValue(c as Control, recursive as Boolean)
   Dim dtp as DateTimePicker = TryCast(c, DateTimePicker)
   If dtp IsNot Nothing Then dtp.Value = Now()
   ' Blah, Blah, Blah
End Sub

Edit: If the thought of Evil extension methods that ignore NullReferenceExceptions don't make you cringe:

编辑:如果忽略 NullReferenceExceptions 的 Evil 扩展方法的想法不会让您感到畏缩:

<Extension()> _
Public Shared Sub ClearValue(c as CheckBox)
   If c IsNot Nothing Then c.Checked = False
End Sub

TryCast(ctrl, CheckBox).ClearValue()

回答by Imran

here is the code to get all control of a Form's All GroupControls and you can do something in the GroupBox Control

这是获取窗体所有 GroupControls 的所有控制权的代码,您可以在 GroupBox 控件中执行某些操作

Private Sub GetControls()
    For Each GroupBoxCntrol As Control In Me.Controls
        If TypeOf GroupBoxCntrol Is GroupBox Then
            For Each cntrl As Control In GroupBoxCntrol.Controls
                'do somethin here

            Next
        End If

    Next
End Sub

回答by rjrapson

Why not just have one routine

为什么不只有一个例程

ClearAllControls(ByRef container As Control, Optional ByVal Recurse As Boolean = True)

You can recurse into it regardless of what level in the hierarchy you begin the call, from the form level down to a single container.

无论您在层次结构中的哪个级别开始调用,您都可以递归到它,从表单级别到单个容器。

Also, on the TextBox controls, I use Textbox.Text = String.Empty

另外,在 TextBox 控件上,我使用 Textbox.Text = String.Empty

回答by ShoushouLebanon

For Each c In CONTAINER.Controls
    If TypeOf c Is TextBox Then
        c.Text = ""
    End If
Next

Replace the (CONTAINER) by the name of yours (it may be a FORM, a PANEL, a GROUPBOX)
Pay attention to which you had included your controls in.

将 (CONTAINER) 替换为您的名称(可能是 FORM、PANEL、GROUPBOX)
注意您已将控件包含在其中。

回答by Sekhar Babu

Here it works for all inner controls.
Add if any other controls do you need to clear.

在这里它适用于所有内部控件。
如果您需要清除任何其他控件,请添加。

Private Sub ClearAll()
    Try
        For Each ctrl As Control In Me.Controls
            If ctrl.[GetType]().Name = "Panel" Then
                ClearControls(ctrl)
            End If

            If ctrl.[GetType]().Name = "GroupBox" Then
                ClearControls(ctrl)
            End If
            If ctrl.[GetType]().Name = "ComboBox" Then
                Dim tb As ComboBox = TryCast(ctrl, ComboBox)
                tb.SelectedText = ""
            End If


            If ctrl.[GetType]().Name = "TabControl" Then
                ClearControls(ctrl)
            End If

            If ctrl.[GetType]().Name = "TextBox" Then
                Dim tb As TextBox = TryCast(ctrl, TextBox)
                tb.Clear()
            End If

            If ctrl.[GetType]().Name = "RadioButton" Then
                Dim tb As RadioButton = TryCast(ctrl, RadioButton)
                tb.Checked = False
            End If

            If ctrl.[GetType]().Name = "CheckBox" Then
                Dim tb As CheckBox = TryCast(ctrl, CheckBox)
                tb.Checked = False
            End If

            If ctrl.[GetType]().Name = "ComboBox" Then
                Dim tb As ComboBox = TryCast(ctrl, ComboBox)
                tb.SelectedIndex = 0
            End If

            If ctrl.[GetType]().Name = "RichTextBox" Then
                Dim tb As RichTextBox = TryCast(ctrl, RichTextBox)
                tb.Clear()

            End If
        Next
    Catch ex As Exception
        MessageBox.Show(ex.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Try
End Sub


Private Sub ClearControls(ByVal Type As Control)

    Try
        For Each ctrl As Control In Type.Controls

            If ctrl.[GetType]().Name = "TextBox" Then
                Dim tb As TextBox = TryCast(ctrl, TextBox)
                tb.Clear()
            End If

            If ctrl.[GetType]().Name = "Panel" Then
                ClearControls(ctrl)
            End If

            If ctrl.[GetType]().Name = "GroupBox" Then
                ClearControls(ctrl)
            End If

            If ctrl.[GetType]().Name = "TabPage" Then
                ClearControls(ctrl)
            End If

            If ctrl.[GetType]().Name = "ComboBox" Then
                Dim tb As ComboBox = TryCast(ctrl, ComboBox)
                tb.SelectedText = ""
            End If

            If ctrl.[GetType]().Name = "RadioButton" Then
                Dim tb As RadioButton = TryCast(ctrl, RadioButton)
                tb.Checked = False
            End If

            If ctrl.[GetType]().Name = "CheckBox" Then
                Dim tb As CheckBox = TryCast(ctrl, CheckBox)
                tb.Checked = False
            End If

            If ctrl.[GetType]().Name = "RichTextBox" Then
                Dim tb As RichTextBox = TryCast(ctrl, RichTextBox)
                tb.Clear()

            End If
        Next
    Catch ex As Exception
        MessageBox.Show(ex.Message, "Error Message", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Try
End Sub

回答by dmcgill50

This comes straight from an articlediscussing techniques to use now that Control Arrays have been done away with going from VB6 to VB.NET.

这直接来自一篇讨论现在使用的技术的文章,因为控件数组已经从 VB6 过渡到 VB.NET。

Private Sub ClearForm(ByVal ctrlParent As Control)
    Dim ctrl As Control
    For Each ctrl In ctrlParent.Controls
        If TypeOf ctrl Is TextBox Then
           ctrl.Text = ""
        End If
        ' If the control has children, 
        ' recursively call this function
        If ctrl.HasChildren Then
            ClearForm(ctrl)
        End If
    Next
End Sub

回答by theraccoonbear

I've done something similar and this is basically how I went about doing it. The only change I might suggest would be instead of overloading the method, just make the passed in type a Control and you can use the same version for GroupBox, Panel, or any other container control that provides a .Controls property. Other than that, I think the definition of "clearing" a control can be somewhat ambiguous and thus there's no Clear() method belonging to the Control class so you need to implement what that means for your purposes for each control type.

我做过类似的事情,这基本上就是我要做的事情。我可能建议的唯一更改是不要重载该方法,只需将传入的类型设为 Control,您就可以对 GroupBox、Panel 或任何其他提供 .Controls 属性的容器控件使用相同的版本。除此之外,我认为“清除”控件的定义可能有些模棱两可,因此没有属于 Control 类的 Clear() 方法,因此您需要为每种控件类型的目的实现这意味着什么。

回答by user3692282

Public Sub raz(lst As Control.ControlCollection, Optional recursive As Boolean = True)
    For Each ctrl As Control In lst
        If TypeOf ctrl Is TextBox Then
            CType(ctrl, TextBox).Clear()
        End If

        If TypeOf ctrl Is MaskedTextBox Then
            CType(ctrl, MaskedTextBox).Clear()
        End If

        If TypeOf ctrl Is ComboBox Then
            CType(ctrl, ComboBox).SelectedIndex = -1
        End If

        If TypeOf ctrl Is DateTimePicker Then
            Dim dtp As DateTimePicker = CType(ctrl, DateTimePicker)
            dtp.CustomFormat = " "
        End If

        If TypeOf ctrl Is CheckedListBox Then
            Dim clbox As CheckedListBox = CType(ctrl, CheckedListBox)
            For i As Integer = 0 To clbox.Items.Count - 1
                clbox.SetItemChecked(i, False)
            Next
        End If

        If TypeOf ctrl Is RadioButton Then
            CType(ctrl, RadioButton).Checked = False

        End If

        If recursive Then
            If TypeOf ctrl Is GroupBox Then
                raz(CType(ctrl, GroupBox).Controls)
            End If
        End If
    Next
End Sub

回答by ElektroStudios

I present you my ControlIteratorClass

我向你展示我的ControlIterator课堂

Source: http://pastebin.com/dubt4nPG

来源:http: //pastebin.com/dubt4nPG

Some usage examples:

一些使用示例:

 ControlIterator.Disable(CheckBox1)

 ControlIterator.Enable({CheckBox1, CheckBox2})

 ControlIterator.Check(Of CheckBox)(Me)

 ControlIterator.Uncheck(Of CheckBox)(Me.GroupBox1)

 ControlIterator.Hide(Of CheckBox)("1")

 ControlIterator.PerformAction(Of CheckBox)(Sub(ctrl As CheckBox) ctrl.Visible = True)

 ControlIterator.AsyncPerformAction(RichTextBox1,
                                    Sub(rb As RichTextBox)
                                        For n As Integer = 0 To 9
                                            rb.AppendText(CStr(n))
                                        Next
                                    End Sub)

 ControlIterator.PerformAction(Me.Controls, Sub(c As Control)
                                                c.BackColor = Color.Green
                                            End Sub)