[Last Call] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1527
  • Last Modified:

Adding timers to dynamically created controls in vb.net

With some excellent help from others, I've created [pieced added/modifed together from more intelligent peoples help ] a ControlArray Class that when called, creates and adds buttons and text boxes on a "row".  Each click of a static Add button on my form creates a new row of dynamic buttons below it on the form. I have the code funtioning to add/remove rows by clicking the appropriate button the row needing action taken.  

Problem:
I need, when each of the rows are created, to create an run a timer with realtime, but independent updates on time elapsed.  I have created and tested my timer code that works for a single timer to start, pause, stop contine etc.
However, as I'm learning, a timer is NOT a control so it cannot be added to my controlArray class OR I'm doing something wrong.  

Question:
How do I add timer code to create independent timers for each row when my dynmic control rows are created?

I've attached the code for the controlArray and the code I wrote to do my timer functions. I know the code is crude as I'm just learning. Please suggest and criticize but try to keep your statements to upper beginner or intermediate with pointers on where to research what you're suggesting so I can learn and understand.

Thanks for any help/thoughts to this newbie programmer.


thanx
daver
TimerCode.txt
ControlArray.txt
0
David Bird
Asked:
David Bird
  • 4
  • 3
1 Solution
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
I would suggest you use the StopWatch() class to keep track of the elapsed time for each Button: *One StopWatch instance for each Button*
http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx

Then use only ONE "master" Timer to control all of the StopWatches and update their associated Buttons.  I wouldn't use System.Timers.Timer either...just use the standard Timer found in the ToolBox (System.Windows.Forms.Timer).

Here is a simple example showing how to use the StopWatch class:
Public Class Form1

    Private clock As New Label
    Private ticker As New System.Windows.Forms.Timer
    Private SW As New Stopwatch

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        clock.Width = 255 : clock.Height = 55 : clock.Left = 35 : clock.Top = 50
        Me.Controls.Add(clock)
        AddHandler ticker.Tick, AddressOf ticker_Tick
    End Sub

    Private Sub ticker_Tick(sender As Object, e As System.EventArgs)
        UpdateClock()
    End Sub

    Private Sub UpdateClock()
        btnStart.Text = FormatTimeSpan(SW.Elapsed)
    End Sub

    Private Sub btnStart_Click(sender As System.Object, e As System.EventArgs) Handles btnStart.Click
        ticker.Interval = 1000
        SW.Start()
        ticker.Start()
    End Sub

    Private Sub btnStop_Click(sender As System.Object, e As System.EventArgs) Handles btnStop.Click
        SW.Stop()
        ticker.Stop()
    End Sub

    Private Function FormatTimeSpan(ByVal pTS As TimeSpan)
        Return String.Format("{0}:{1}:{2}", pTS.Hours.ToString("00"), pTS.Minutes.ToString("00"), pTS.Seconds.ToString("00"))
    End Function

End Class

Open in new window


Let me know when you've digested that and whether you think it'll work for you.  If yes, I'll post how to modify your control array class accordingly.  Otherwise feel free to ask questions...
0
 
David BirdPartnerAuthor Commented:
Awesome.  This will work fine. I had started with the Stopwatch feature but it was throwing cross-thread errors (so was timer) as I was updating the controls from within the event handler.  I had just moved to timers as there was more code to play with on the 'Net.
Thank you.  
I'm ready for the integration piece now if you don't mind.  I'm anxious to see how you create multiple SW's on a Single timer and update/address them in a dynamic array of controls.  

thank you so much for helping!

daver
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
Try this out.  I've only posted the sections which I've changed.  Those changes are BOLD colored:

Public Class ControlArray
    Inherits System.Collections.CollectionBase

    Private ReadOnly HostForm As System.Windows.Forms.Form
   Private StopWatches As New Dictionary(Of Button, Stopwatch)
    Private WithEvents Tmr As New System.Windows.Forms.Timer


    Public Sub New(ByVal host As System.Windows.Forms.Form)
        HostForm = host
       Tmr.Interval = 1000
        Tmr.Start()

    End Sub

   Private Sub Tmr_Tick(sender As Object, e As System.EventArgs) Handles Tmr.Tick
        For Each kvp As KeyValuePair(Of Button, Stopwatch) In StopWatches
            If kvp.Value.IsRunning Then
                kvp.Key.Text = FormatTimeSpan(kvp.Value.Elapsed)
            End If
        Next
    End Sub


   Private Function FormatTimeSpan(ByVal pTS As TimeSpan)
        Return String.Format("{0}:{1}:{2}", pTS.Hours.ToString("00"), pTS.Minutes.ToString("00"), pTS.Seconds.ToString("00"))
    End Function


    Public Sub ClickHandler(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim btn As Button = CType(sender, System.Windows.Forms.Button)
       If StopWatches.ContainsKey(btn) Then
            StopWatches(btn).Start()
        End If
   End Sub

    Public Function AddNewButton() As System.Windows.Forms.Button
        ' Create a new instance of the Button class.

        Dim aButton As New System.Windows.Forms.Button()
        gbintRow += 1
        Dim intTopLoc As Integer = gbintRow * 25 + 15

        ' Add the button to the collection's internal list.
        Me.List.Add(aButton)

        ' Add the button to the controls collection of the form
        ' referenced by the HostForm field.

        HostForm.Controls.Add(aButton)

        ' Set intial properties for the button object.

        aButton.Top = intTopLoc
        aButton.Left = 15
        aButton.Tag = gbintRow
        aButton.Text = "Start " & gbintRow.ToString.Trim
       aButton.Size = New System.Drawing.Size(75, 32)
        aButton.Image = Global.KeepMyTime.My.Resources.StopSign.ToBitmap
        AddHandler aButton.Click, AddressOf ClickHandler

       'Attempt a timer here
        StopWatches.Add(aButton, New Stopwatch)


        'Second Button------------

        aButton = New System.Windows.Forms.Button()
        ' Add the button to the collection's internal list.
        Me.List.Add(aButton)
        ' Add the button to the controls collection of the form
        ' referenced by the HostForm field.
        HostForm.Controls.Add(aButton)

        ' Set intial properties for the button object.
        aButton.Top = intTopLoc
        aButton.Left = 100
        ' aButton.Tag = "Row " & intRow.ToString.Trim
        aButton.Tag = gbintRow
        'aButton.Text = "Stop " & gbintRow.ToString.Trim
        aButton.Size = New System.Drawing.Size(32, 32)
        'aButton.Image = Global.KeepMyTime.My.Resources.StopSign.ToBitmap
        AddHandler aButton.Click, AddressOf StopClickHandler

        Dim aTextBox As New System.Windows.Forms.TextBox
        Me.List.Add(aTextBox)
        HostForm.Controls.Add(aTextBox)
        aTextBox.Top = intTopLoc + 3
        aTextBox.Left = 180
        aTextBox.Tag = gbintRow
        aTextBox.Size = New System.Drawing.Size(205, 22)

        Return aButton
    End Function

    Public Sub RemoveByText(ByVal pm_Text As Integer)
        Dim btn As Button = Nothing
        Dim txtBox As TextBox = Nothing
        Dim i As Integer
        For i = 1 To 3
            For Each btnIterator As Control In Me.List
                If btnIterator.Tag = pm_Text Then
                    txtBox = TryCast(btnIterator, TextBox)
                    btn = TryCast(btnIterator, Button)
                    Exit For
                End If
            Next
            ' Check to be sure there is a button to remove.
            If btn IsNot Nothing Then
               If StopWatches.ContainsKey(btn) Then
                    StopWatches.Remove(btn)
                End If
               HostForm.Controls.Remove(btn)
                Me.List.Remove(btn)
            End If
            If txtBox IsNot Nothing Then
                HostForm.Controls.Remove(txtBox)
                Me.List.Remove(txtBox)
            End If
        Next
        gbintRow -= 1
        MoveButtonsUp(pm_Text)
    End Sub

End Class
0
Free learning courses: Active Directory Deep Dive

Get a firm grasp on your IT environment when you learn Active Directory best practices with Veeam! Watch all, or choose any amount, of this three-part webinar series to improve your skills. From the basics to virtualization and backup, we got you covered.

 
David BirdPartnerAuthor Commented:
That worked perfectly! I don't even need my Timer code anymore.  

It will take me a bit of time to understand a couple of the things you did but that'll be fun to track down and learn. However, I do have a final question please.

I've added code in the ClickHandler to toggle it on and off.
 
       If StopWatches.ContainsKey(btn) Then
            'toggle on and/or off
            If StopWatches(btn).IsRunning = True Then
                StopWatches(btn).Stop()
            Else
                StopWatches(btn).Start()
            End If

However, I don't understand how to start the timer immediately after it is created with the code you wrote:

        StopWatches.Add(aButton, New Stopwatch)

How do I address THIS button after it's creation to start the timer initially?

Thanx
daver
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
If you want it to start immediately then:

    Dim SW As New StopWatch
    StopWatches.Add(aButton, SW)
    SW.Start()
0
 
David BirdPartnerAuthor Commented:
Thank you for your help and clear explanations! You're as awesome a communicator as you are an amazing coder.
0
 
Mike TomlinsonMiddle School Assistant TeacherCommented:
No problem. Let me know if you have any questions regarding the implementation...  =)
0

Featured Post

Efficient way to get backups off site to Azure

This user guide provides instructions on how to deploy and configure both a StoneFly Scale Out NAS Enterprise Cloud Drive virtual machine and Veeam Cloud Connect in the Microsoft Azure Cloud.

  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now