2016-05-05 6 views
-1

Ja, von Zeit für die Forschung ausgeben ich weiß, dassIterate durch Timer dann ihre Namen bekommen

Ein Timer ist eine Komponente nicht eine Kontrolle, so dass es nicht in der Steuersammlung wird. Dies ist ein Fall, wo es wahrscheinlich besser ist, nicht verwenden Sie eine allgemeine Schaltfläche Click-Handler, da es nicht vereinfacht alles ist. (Source)

Aber, gibt es etwas, was ich tun kann, um meine derzeitige Situation zu bestehen?

Was ich will, ist, wenn ein Benutzer auf eine Schaltfläche klickt (Ich habe viele Tasten) wird es festzustellen, ob der Status dieser Taste Start oder Stop dann, wenn es stop es sollte start ist.

Stop und Start entsprechen dem Timer, die Anzahl der Tasten entspricht der Anzahl der Timer, die ich habe.

Ich kann verknüpft sie leicht durch eine Funktion wie diese

Schaffung
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 

Mein Problem ist, dieser Teil des Codes

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 

ich durch Iterieren durch alle den Namen des Timers zu bekommen versuche Objekte in meinen Formen. Ich kann leicht alle Objekte gruppieren, indem ich sie richtig benenne, zum Beispiel in set 1 Ich habe btnStatus1 und tmrString1 dann in set 2 Ich habe btnStatus2 und tmrString2, nur die letzte Zeichenkette, die eine Zahl ändert.

+0

Möchten Sie stattdessen "Tag" verwenden? –

+0

Wenn "Tag" mir helfen wird, den Namen des Timers zu bekommen, ist es okay. :) In meinem Code versuche ich nur das 'Tag' zu verwenden, weil jemand es vorgeschlagen hat. –

+0

In Ihrem Fall sieht Ihr Code mit 'Tag' gut aus. Alles, was Sie jetzt tun müssen, ist das "Tag" Ihrer Timer einzeln zu ändern. –

Antwort

1

Ich habe fast immer gefunden, dass die Suche nach Komponenten nach Namen zur Laufzeit irgendwann fehlschlägt, wenn Sie das Formular weiterhin bearbeiten/ändern. Es ist meiner Meinung nach viel besser, sicherzustellen, dass Sie eine Kompilierzeitprüfung haben.

Ich würde diesen Code stattdessen tun:

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 

Die Dictionary(Of Button, Timer) hart Codes die Zuordnung in so dass es keine Notwendigkeit für die Timer zu suchen ist. Dies verringert auch die Notwendigkeit, die Tasten und Timer tatsächlich zu benennen und zu markieren.


Gerade für den Spaß von ihm habe ich auf Ihre Antwort auf meinen Kommentar auf die Frage, Ihre vollständige Lösung bei der Umsetzung auf Basis eines Go hatte. Hier ist es:

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 

Ich habe Microsoft Reactive Framework für alle Event-Handling und Timer verwendet. Sie müssen nur "Rx-WinForms" in Ihre App einbinden, um sie zu verwenden.

Sie werden sehen, dass parts eine Liste der Schaltfläche, numerisches hoch/runter, Textfeld und eine Portnummer enthält.

query übernimmt diese Teile und erstellt Handler für die Tastenklicks. Basierend auf dem Text innerhalb der Schaltfläche startet es Timer basierend auf den numerischen Höhen-/Tiefensteuerelementen und Textfeldern. Query erzeugt einfach einen Strom von Werten in der Form { .Text = "Foo", .Port = 1 }. query verwendet auch einen Operator .Do(...), um die Benutzeroberfläche zu aktualisieren, während die Timer ausgeführt werden.

Schließlich nimmt der Code .Subscribe(...) diese Werte und fügt sie in meiner App zu einem Textfeld im Formular hinzu, so dass ich die gesamte Ausgabe sehen kann.

Hier ist ein Beispiel für die Form, wie ich es mit wurde:

form

Ich hoffe, das von Interesse ist.

+0

Oh, danke! Ich werde das später versuchen. –

+0

So unglaublich! Ich danke dir sehr! Ja, das ist von meinem Interesse! Ich studiere jetzt das Nuget. –

+0

Es funktioniert jetzt! Mein Dank ist nicht genug, um meine Dankbarkeit auszudrücken. Ein Code, der so großartig ist! –

1

Ich habe gerade Ihren Code vereinfacht. Hier ist sie:

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 

Alles, was Sie jetzt tun müssen, ist passen die Tag jedes Timer seiner Name entspricht.

+0

Oh, 'Alles, was Sie jetzt tun müssen, ist die Übereinstimmung des Namens jedes Timers mit seinem Namen. Das ist der Teil, der mir unklar ist. Entschuldigung, könnten Sie ein Beispiel dafür geben? –

+0

Sind Ihre 'Timer' zu' Design-Zeit' erstellt? –

+0

Ahhm, nicht sicher? Ich ziehe sie und lasse sie fallen. Benennen Sie jede von ihnen um –