【问题标题】:Recursive type-specific control enable.state setting递归类型特定控制 enable.state 设置
【发布时间】:2015-08-07 16:35:10
【问题描述】:

我正在尝试构建一个快速子组件,它将禁用表单上和该表单上的任何容器中给定类型 T 的所有控件,例如在 GroupBox

由于某种原因,我目前(如下)令人讨厌的代码似乎忽略了 GroupBox 控件(我意识到我只用 Form 容器尝试过它,否则它确实有效)。

Private Sub ChangeControlEnabledState(Of T As Control)(cc As ContainerControl, state As Boolean)
    Dim cl As ControlCollection = cc.Controls
    For Each c As Object In cc.Controls ' Iterate through every object in the container
        If TypeOf c Is T Then   ' Check if the object matches the type to set the state on
            CType(c, T).Enabled = state ' Set the state on the matching object
        ElseIf TypeOf c Is ContainerControl Then    ' Check if the object is a "sub" container type
            ChangeControlEnabledState(Of T)(c, state)   ' Recurse to handle the controls within the "sub" container
        End If
    Next
End Sub

'Usage
ChangeControlEnabledState(Of Button)(Me, False) 'Changes all buttons on this form to Button.Enabled = false

也许GroupBox 不是ContainerControl

编辑: 调整为:

        For Each c As Control In cc ' Iterate through every object in the container
            If TypeOf c Is T Then   ' Check if the object matches the type to set the state on
                CType(c, T).Enabled = state ' Set the state on the matching object
            ElseIf c.HasChildren Then  ' Check if the control has children
                ChangeControlEnabledState(Of T)(c.Controls, state)   ' Recurse to handle the child controls
            End If
        Next

但这会在尝试递归时在第一个 GroupBox 上引发异常:

System.InvalidCastException {"[A]ControlCollection 不能转换为 [B]ControlCollection。类型 A 源自上下文 'System.Windows.Forms,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089'默认'在位置'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Windows.Forms\v4.0_4.0.0.0__b77a5c561934e089\System.Windows.Forms.dll'。类型B源自'System.Windows。表单,版本 = 4.0.0.0,文化 = 中性,PublicKeyToken=b77a5c561934e089' 在位置 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Windows.Forms\v4.0_4.0.0 的上下文“默认”中。 0__b77a5c561934e089\System.Windows.Forms.dll'."} System.InvalidCastException

据我有限的理解,这似乎是说不能将类型 X 转换为类型 X,因为它是类型 X...

【问题讨论】:

  • 我试过改成ElseIf (c.GetType).GetField("Controls") IsNot Nothing Then ...,但没有骰子。
  • 开启 Option Strict 并且不要将循环迭代器装箱
  • @Plutonix 想想如果我让他紧张的话,我父亲会这么说 :p 但否则恐怕我不知道那是什么意思
  • Control.ControlCollection 而不是 Sub 参数类型的 ControlCollection 可以解决异常。愚蠢的通用对象不是通用的,除非它们是通用的。但有时他们仍然不...脾气暴躁。

标签: vb.net controls


【解决方案1】:

不确定这会有所帮助,但我使用 control.haschildren 来确定递归调用。

Private Sub SetEnterHandler(ByVal ParentCtrl As Control)
    'recursive call to find all controls that can have focus
    For Each c As Control In ParentCtrl.Controls
        If c.HasChildren Then
            SetEnterHandler(c)
        Else
            'do non-container stuff here
        End If
    Next
End Sub

我从一个初始化子中调用这个子:

    For Each c As Control In Me.Controls
        If c.HasChildren Then SetEnterHandler(c)
    Next

表单在哪里。

【讨论】:

  • 好的,这有助于确定是否有完美的子控件,现在我只需要能够将父控件转换为一些可以接受任何父控件的通用控件(不仅仅是ContainerControl,它结果是不是任何包含控件的控件)。我是否必须像Control 那样通用,还是有比涵盖所有可以有子控件的控件更严格的类型?
  • 不,我认为控制已经尽可能严格了。
  • Private Sub ChangeControlEnabledState(Of T As Control)(cc As Control, state As Boolean) For Each c As Control In cc.Controls If TypeOf c is T Then CType(c, T).Enabled = state ElseIf c.HasChildren Then ChangeControlEnabledState(Of T)(c, state) End If Next End Sub
【解决方案2】:

此错误是因为ContainerControl 是在“System.Windows.Forms”命名空间中的Control 类中定义的,并且它是表单和任何控件的父类。
Control 的所有子类都在生成它们自己的 ControlCollection 类,而这并不是真正需要的。

只要用Control.ContainerControl显式定义,这个错误就会消失!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-13
    • 2020-05-26
    • 2023-03-12
    • 1970-01-01
    • 2018-01-31
    • 1970-01-01
    • 1970-01-01
    • 2013-06-24
    相关资源
    最近更新 更多