我想创建一个程序来阻止任何给定表单的所有计时器。虽然在建造它时说
"组分'不是System.Windows.Forms.Form"。
的成员
以下是代码:
yyyymmdd_textbox1(.txt)
答案 0 :(得分:1)
您可以使用反射:
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
答案 1 :(得分:1)
正如我在评论中更正的那样,Controls
集合不包含组件 - 它只包含控件。对非可视组件(如计时器)的引用保存在私有Container
字段中,通常称为components
。 Container
字段根本不是基本Form
类的一部分。它由表单设计者在需要它的每个表单上单独声明和实现。由于它不是基类的成员,因此没有简单的方法可以在任何给定的表单上访问它。即使它是基类的成员,可访问性仍然是一个问题,因为它通常被声明为私有字段。
保持正确类型检查的安全方法是创建一个接口:
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
但是,如果您真的不关心类型检查,并且不介意性能略有下降,您可以使用反射来查找表单对象中的私有字段并提取其值: / p>
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