Vb.net 遍历计时器,然后获取它们的名称
是的,通过花时间进行研究,我意识到 计时器是一个组件而不是控件,因此它不会位于 控制集合。在这种情况下,最好不要这样做 使用公共按钮单击处理程序,因为它不会简化 任何东西() 但是,我能做些什么来改变我的现状吗 我想要的是,每当用户单击一个按钮(我有许多按钮)时,它将确定该按钮的状态是Vb.net 遍历计时器,然后获取它们的名称,vb.net,timer,Vb.net,Timer,是的,通过花时间进行研究,我意识到 计时器是一个组件而不是控件,因此它不会位于 控制集合。在这种情况下,最好不要这样做 使用公共按钮单击处理程序,因为它不会简化 任何东西() 但是,我能做些什么来改变我的现状吗 我想要的是,每当用户单击一个按钮(我有许多按钮)时,它将确定该按钮的状态是Start还是Stop,如果是Stop,它应该Start 停止和启动对应计时器,按钮的数量对应计时器的数量 通过创建这样的函数,我可以轻松地将它们链接起来 Function isBTNStatusEnabled(s
Start
还是Stop
,如果是Stop
,它应该Start
停止和启动对应计时器,按钮的数量对应计时器的数量
通过创建这样的函数,我可以轻松地将它们链接起来
Function isBTNStatusEnabled(sender As Object) As Boolean
Dim result As Boolean = False
Dim btnStatus As Button = DirectCast(sender, Button)
Dim btnStatusNumber As String = btnStatus.Name.Substring(btnStatus.Name.Length - 1)
Console.WriteLine("Found the " & btnStatus.Name)
If btnStatus.Text = "Start" Then
btnStatus.Text = "Stop"
result = True
btnStatus.BackColor = Color.Red
Else
btnStatus.Text = "Start"
result = False
btnStatus.BackColor = SystemColors.Control
End If
For Each frmTesterObjects As Object In Me.components.Components
If TypeOf frmTesterObjects Is Timer And DirectCast(frmTesterObjects, Timer).Tag.ToString = "tmrString" & btnStatusNumber Then
'what to do
Console.WriteLine("Timer name: " & DirectCast(frmTesterObjects, Timer).Tag.ToString)
End If
Next frmTesterObjects
Return result
End Function
我的问题是这部分代码
If TypeOf frmTesterObjects Is Timer And DirectCast(frmTesterObjects, Timer).Tag.ToString = "tmrString" & btnStatusNumber Then
Console.WriteLine("Timer name: " & DirectCast(frmTesterObjects, Timer).Tag.ToString)
End If
我试图通过遍历表单中的所有对象来获取计时器的名称。通过正确命名,我可以轻松地对所有对象进行分组,例如在
set1
中,我有btnStatus1
和tmrString1
,然后在set2
中,我有btnStatus2
和tmrString2
,只有最后一个数字字符串发生了变化。我刚刚简化了您的代码。这是:
For Each x In Me.components.Components.OfType(Of Timer)()
If x.Tag = "tmrString" & btnStatusNumber Then
Console.WriteLine("Timer name: " & x.Tag)
End If
Next
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim parts =
{
New With {.Button = Button1, .NumericUpDown = NumericUpDown1, .TextBox = TextBox1, .Port = 1},
New With {.Button = Button2, .NumericUpDown = NumericUpDown2, .TextBox = TextBox2, .Port = 2},
New With {.Button = Button3, .NumericUpDown = NumericUpDown3, .TextBox = TextBox3, .Port = 3}
}
Dim query =
From p In parts
Select
Observable _
.FromEventPattern(Sub(h) AddHandler p.Button.Click, h, Sub(h) RemoveHandler p.Button.Click, h) _
.ObserveOn(Me) _
.Do(Sub(ep)
Dim start = p.Button.Text = "Start"
p.Button.Text = If(start, "Stop", "Start")
p.Button.BackColor = If(start, Color.Red, SystemColors.Control)
p.NumericUpDown.Enabled = Not start
p.TextBox.Enabled = Not start
End Sub) _
.Select(Function(ep) _
Observable _
.Interval(TimeSpan.FromSeconds(p.NumericUpDown.Value)) _
.Select(Function(n) New With {p.TextBox.Text, p.Port}) _
.TakeWhile(Function(x) p.Button.Text = "Stop")) _
.Switch()
query _
.Merge() _
.ObserveOn(Me) _
.Subscribe(
Sub(x)
TextBox4.Text = TextBox4.Text + String.Format("Text ""{0}"" on Port ""{1}""{2}", x.Text, x.Port, Environment.NewLine)
End Sub)
End Sub
现在您所要做的就是匹配每个
计时器的标记
,该标记对应于其名称
,我几乎总是发现,如果继续维护/修改表单,在运行时按名称搜索组件最终将失败。在我看来,确保进行编译时检查要好得多
我将改为执行以下代码:
Function isBTNStatusEnabled(sender As Object) As Boolean
Dim button2Timer = New Dictionary(Of Button, Timer) From
{{Button1, Timer1}, {Button2, Timer2}, {Button3, Timer3}}
Dim result As Boolean = False
Dim btnStatus As Button = DirectCast(sender, Button)
Console.WriteLine("Found the " & btnStatus.Name)
If btnStatus.Text = "Start" Then
btnStatus.Text = "Stop"
result = True
btnStatus.BackColor = Color.Red
Else
btnStatus.Text = "Start"
result = False
btnStatus.BackColor = SystemColors.Control
End If
Console.WriteLine("Timer name: " & button2Timer(btnStatus).Tag.ToString())
Return result
End Function
字典(按钮、计时器)
硬编码映射,因此无需搜索计时器。这也减轻了对按钮和计时器实际命名和标记的需要
只是为了好玩,我试着根据你对我对这个问题的评论的回答来实现你的完整解决方案。这是:
For Each x In Me.components.Components.OfType(Of Timer)()
If x.Tag = "tmrString" & btnStatusNumber Then
Console.WriteLine("Timer name: " & x.Tag)
End If
Next
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim parts =
{
New With {.Button = Button1, .NumericUpDown = NumericUpDown1, .TextBox = TextBox1, .Port = 1},
New With {.Button = Button2, .NumericUpDown = NumericUpDown2, .TextBox = TextBox2, .Port = 2},
New With {.Button = Button3, .NumericUpDown = NumericUpDown3, .TextBox = TextBox3, .Port = 3}
}
Dim query =
From p In parts
Select
Observable _
.FromEventPattern(Sub(h) AddHandler p.Button.Click, h, Sub(h) RemoveHandler p.Button.Click, h) _
.ObserveOn(Me) _
.Do(Sub(ep)
Dim start = p.Button.Text = "Start"
p.Button.Text = If(start, "Stop", "Start")
p.Button.BackColor = If(start, Color.Red, SystemColors.Control)
p.NumericUpDown.Enabled = Not start
p.TextBox.Enabled = Not start
End Sub) _
.Select(Function(ep) _
Observable _
.Interval(TimeSpan.FromSeconds(p.NumericUpDown.Value)) _
.Select(Function(n) New With {p.TextBox.Text, p.Port}) _
.TakeWhile(Function(x) p.Button.Text = "Stop")) _
.Switch()
query _
.Merge() _
.ObserveOn(Me) _
.Subscribe(
Sub(x)
TextBox4.Text = TextBox4.Text + String.Format("Text ""{0}"" on Port ""{1}""{2}", x.Text, x.Port, Environment.NewLine)
End Sub)
End Sub
我在所有事件处理和计时器中都使用了微软的反应式框架。你只需要在你的应用程序中加入“Rx WinForms”就可以使用它
您将看到,部分
包含按钮列表、数字向上/向下、文本框和端口号
query
获取这些部分并为按钮单击创建处理程序。根据按钮内的文本,它根据数字上/下控件和文本框启动计时器。查询只是以{.Text=“Foo”,.Port=1}
的形式生成一个值流<代码>查询
还使用.Do(…)
操作符在计时器运行时更新UI
最后,.Subscribe(…)
代码获取这些值,并在我的应用程序中,将它们添加到表单上的文本框中,以便我可以查看所有输出
下面是我正在使用的表单示例:
我希望您对此感兴趣。您想改用Tag
吗?如果Tag
可以帮助我获取计时器的名称,那就可以了。:)在我的代码中,我只是尝试使用标记
,因为有人建议使用它。在您的情况下,您的代码使用标记
看起来很好。您现在所要做的就是分别更改计时器的标记。您可以发布一个答案吗?从Button派生您自己的类,添加一个属性来存储计时器。哦,您现在所要做的就是将每个计时器的标记与其名称相匹配。
这是我不清楚的部分。对不起,你能提供一个例子吗?你的定时器是在设计时创建的吗?嗯,不确定?我拖放它们。重命名每个计时器上的设计时间
,单击每个计时器
,您可以看到其属性
,其中有一个标记
。将其更改为您的计时器的名称。哦,很高兴知道。很抱歉出现错误,我尚未测试该代码。快乐编码:)太棒了!非常感谢你!是的,这是我感兴趣的!我现在正在研究nuget,它现在起作用了!我的感谢还不足以表达我的感激之情。一个非常棒的代码!