通过计时器迭代然后得到他们的名字

时间:2016-05-05 01:25:06

标签: vb.net timer

是的,花时间研究我知道

  

定时器是一个组件而不是一个控件,所以它不会位于   控制系列。这是一个可能更好的情况   使用常见的按钮单击处理程序,因为它没有简化   任何东西。 (Source

但是,我能做些什么才能通过目前的情况?

我想要的是每当用户点击一个按钮(我有很多按钮)时,它将确定该按钮的状态是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

我试图通过遍历表单中的所有对象来获取计时器的名称。我可以通过正确命名它们来轻松地对所有对象进行分组,例如在set 1我有btnStatus1tmrString1然后在set 2我有btnStatus2和{ {1}},只有最后一个数字字符串会发生变化。

2 个答案:

答案 0 :(得分:1)

我刚刚简化了您的代码。这是:

   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

现在,您只需匹配与其Tag对应的每个Timer的{​​{1}}。

答案 1 :(得分:1)

我几乎总是发现,如果继续维护/修改表单,在运行时按名称搜索组件最终会失败。在我看来,确保你有一个编译时检查要好得多。

我会改为执行此代码:

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

Dictionary(Of Button, Timer)对映射进行硬编码,因此无需搜索Timer。这也减少了实际命名和标记按钮和计时器的需要。

为了好玩,我根据你对这个问题的评论回答,实现了你的完整解决方案。这是:

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

我已经将Microsoft的Reactive Framework用于所有事件处理和计时器。您只需要在您的应用中使用NuGet“Rx-WinForms”即可使用它。

您会看到parts包含按钮列表,数字上/下,文本框和端口号。

query获取这些部分并为按钮点击创建处理程序。根据按钮内的文本,它会根据数字向上/向下控件和文本框启动计时器。查询只是以{ .Text = "Foo", .Port = 1 }的形式生成值流。 <{1}}也使用query运算符在计时器运行时更​​新UI。

最后,.Do(...)代码会获取这些值,并在我的应用中将它们添加到表单上的文本框中,以便我可以看到所有输出。

以下是我使用它时的表单示例:

form

我希望这很有意思。