2016-05-05 45 views
-1

是,通過研究花時間我知道迭代通過定時器然後得到他們的名字

一個定時器是一個組件不是控制,所以它不會設在 控件集合。在這種情況下,最好不要 使用常見的按鈕點擊處理程序,因爲它不會簡化 的任何操作。 (Source

但是,有什麼我可以做,以通過我目前的情況?

我想只要用戶點擊一個按鈕(我有許多按鈕),它將確定該按鈕的狀態是StartStop那麼,如果它是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我有btnStatus2tmrString2,只有最後一個字符串是一個數字的變化。

+0

你想用'Tag'代替嗎? –

+0

如果'Tag'會幫助我得到計時器的名字,那就好了。 :)在我的代碼中,我只是試圖使用'Tag',因爲有人提出了這個問題。 –

+0

就你而言,你的代碼使用'Tag'看起來很好。你現在要做的就是單獨改變定時器的標籤。 –

回答

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 }形式的值流。 query還使用.Do(...)運算符在定時器運行時更​​新UI。

最後,.Subscribe(...)代碼取這些值,並在我的應用程序中將它們添加到窗體上的文本框中,以便我可以看到所有輸出。

下面是形式的一個例子,因爲我是用它:

form

我希望這是感興趣的。

+0

哦,謝謝!我稍後再試。 –

+0

太神奇了!非常感謝!是的,這是我的興趣!我正在研究nuget。 –

+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 

所有你現在要做的是與對應於它的Name每個TimerTag

+0

哦,''你現在所要​​做的就是匹配每個計時器對應其名稱的標籤。'這是我不清楚的部分。對不起,你能提供一個例子嗎? –

+0

你的'定時器'是否在'design-time'創建? –

+0

Ahhm,不確定?我拖放它們。將它們重命名爲 –