Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/vb.net/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net 如何列出其他窗体的所有计时器_Vb.net_Winforms_Timer_Components - Fatal编程技术网

Vb.net 如何列出其他窗体的所有计时器

Vb.net 如何列出其他窗体的所有计时器,vb.net,winforms,timer,components,Vb.net,Winforms,Timer,Components,我想做一个程序,停止任何给定形式的所有计时器。尽管在建造时它说 “组件”不是“System.Windows.Forms.Form”的成员 代码如下: Public Sub _Timers_Stop(frm As Form) For Each itm As Object In frm.components.components If TypeOf (itm) Is Timer Then itm.stop()

我想做一个程序,停止任何给定形式的所有计时器。尽管在建造时它说

“组件”不是“System.Windows.Forms.Form”的成员

代码如下:

Public Sub _Timers_Stop(frm As Form)
        For Each itm As Object In frm.components.components
           If TypeOf (itm) Is Timer Then
               itm.stop()
           End If
        Next
End Sub

您可以为此使用反射:

Public Sub StopTimers(Form As Form)
    For Each Item In Form.GetType.GetFields(Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public).Where(Function(x) TypeOf x.GetValue(Form) Is Timer)
        Dim Timer As Timer
        Timer = Item.GetValue(Form)
        Timer.Stop()
    Next
End Sub

正如我在注释中更正的那样,
控件
集合不包含组件,它只包含控件。对非可视组件(如计时器)的引用保存在专用
容器
字段中,通常称为
组件
。该
容器
字段根本不是基本
表单
类的一部分。表单设计器在每个需要它的表单上分别声明和实现它。因为它不是基类的成员,所以在任何给定的表单上都无法轻松访问它。即使它是基类的成员,可访问性仍然是一个问题,因为它通常声明为私有字段

这样做的安全方法是创建一个接口,它保留了正确的类型检查:

Public Interface IFormWithComponents
    ReadOnly Property Components As ComponentCollection
End Interface
然后,您可以在每种表单上实施(如适用):

Public Class MyForm
    Implements IFormWithComponents

    Public ReadOnly Property Components As ComponentCollection Implements IFormWithComponents.Components
        Get
            Return components.Components
        End Get
    End Property
End Class
然后,计时器停止方法可以将该接口作为其参数:

Public Sub _Timers_Stop(frm As IFormWithComponents)
    For Each t As Timer In frm.Components.Cast(Of Component).OfType(Of Timer)
       t.stop()
    Next
End Sub
但是,如果您并不真正关心类型检查,也不介意性能稍有下降,您也可以使用反射来查找表单对象中的私有字段并提取其值:

Public Sub _Timers_Stop(frm As Form)
    Dim timers As IEnumerable(Of Timer) = frm.
        GetType().
        GetFields(BindingFlags.FlattenHierarchy Or BindingFlags.Instance Or BindingFlags.NonPublic Or BindingFlags.Public).
        Select(Function(fieldInfo) fieldInfo.GetValue(frm)).
        OfType(Of Container)().
        SelectMany(Function(container) container.Components.OfType(Of Timer)())
    For Each t As Timer In timers
        t.Stop()
    Next
End Sub

这是因为
Form
没有
components
属性(就像错误所说的那样)。只能调用存在的属性。而不是
frm.components.components
,请尝试
frm.Controls
@StevenDoggart:不幸的是组件不是
Controls
集合的一部分。@lamiabed:
components
属性/字段仅由Visual Studio designer创建,您需要将
frm
强制转换到您的特定表单中才能使用它(除非标记为
Private
Protected
)。只需将计时器列表或数组作为该表单的公共属性,这将是直接访问它们的最简单方法。表单的frm.Controls集合可能包含的不仅仅是几个计时器谢谢各位:)我会尝试