Sean Long
Sean Long

Reputation: 2301

Making a button.click event do two different things

I'm working on a simple VB.NET program (just using winforms) and am really terrible at UI management. I'd like to have a single button that starts a process, and then have that same button stop the process.

I'm thinking about having the main form initiate a counter, and the Click event iterate the counter. Then it does a simple check, and if the counter is even it will do thing A and odd does thing B.

Is there a better way, aside from using two buttons or stop/start radio buttons?

Upvotes: 0

Views: 3227

Answers (3)

Andrew Neely
Andrew Neely

Reputation: 908

I've done that exact thing one of two ways. You can use a static variable or toggle the text of the button.

Since your button has two functions, Good design requires you to indicate that to the user. The following code assumes the Button's text is set in Design Mode to "Start", and the code to start and stop your process is in the Subs StartProcess and EndProcess.

Public Sub Button1_Click(ByVal Sender as Object, ByVal e as System.EventArgs)
     If Button1.Text ="Start" Then
            StartProcess()
            Button1.Text="End"
     Else
            EndProcess()
            Button1.Text="Start"
     End IF
End Sub

EDIT

The above solution is fine for a single-language application developed by a small number of developers.

To support multiple languages, developers typically assign all text literals from supporting files or databases. In larger development shops, with multiple programmers, using a display feature of the control for flow-control may cause confusion and regression errors. In those cass, the above technique wouldn't work.

Instead, you could use the Tag property of the button, which holds an object. I would typically use a Boolean, but I used a string just to make more clear as to what's going on.

Public Sub New()
    'Initialize the Tag
    Button1.Tag="Start"
End Sub
    Public Sub Button1_Click(ByVal Sender as Object, ByVal e as System.EventArgs)
         If Button1.Tag.ToString="Start" Then
                StartProcess()
                Button1.Tag="End"
         Else
                EndProcess()
                Button1.Tag="Start"
         End IF
    End Sub

Upvotes: 3

Fabio
Fabio

Reputation: 32445

Just want to show another approach for this task Use .Tag property for your own purpose If .Tag Is Nothing (by default in designer) then start process
If not Nothing -> stop process

Public Sub Button1_Click(ByVal Sender as Object, ByVal e as System.EventArgs)
    If Me.Button1.Tag Is Nothing Then
        StartProcess()
        Me.Button1.Tag = New Object()
        Me.Button1.Text = "End"
    Else
        EndProcess()
        Me.Button1.Tag = Nothing
        Me.Button1.Text = "Start"
    End
End Sub

Upvotes: 1

T.S.
T.S.

Reputation: 19340

This is example in pseudo-code. I don't guarantee that names of methods and event are exactly match real names. But this should provide you a design that you could use for responsive form.

Lets say, your process is running on separate tread, using BackgroundWorker. You setup your worker and start process

Class MyForm

    private _isRunning as boolean
    private _bgWorker as BackgroundWorker

    sub buton_click()
        If Not _isRunning Then 
            _isRunning = true;
            StartProcess()
        Else
            StopProcess()  
        End if  
    end sub

    sub StartProcess()
        ' Setup your worker
        ' Wire DoWork
        ' Wire on Progress 
        ' wire on End
        _bgWorker.RunWorkerAsync()
    End sub          

    sub StopProcess()
        if _isRunning andAlso _bgWorker.IsBusy then 
             ' Send signal to worker to end processed
             _bgWorker.CancelAsync()
        end if
    end sub

    sub DoWork()
        worker.ReportProgress(data) ' report progress with status like <Started>
        ' periodically check if process canceled
        if worker.canceled then
            worker.ReportProgress(data) ' report progress with status like <Cancelling>
            return 
        end if

        ' Do your process and report more progress here with status like <In Progress>
        ' and again periodically check if process canceled
        if worker.canceled then
            worker.ReportProgress(data) ' report progress with status like <Cancelling>
            return 
        end if

        worker.ReportProgress(data) ' report progress with status like <Ending>

    end sub

    sub ReportProgress(data)
        if data = <some process state, like "Started"> then
           btnProcess.Text = "End Process" 
        end if


    End sub

    sub ReportEndOfProcess
        btnProcess.Text = "Start Process"
        _isRunning = false
     end sub

End Class 

Here you can pinpoint the names of methods and events You have to substitute identifiers with real names and create you state or data object, which will carry information from background thread to UI thread, and also an Enum Status that can be part of your custom state object. This should work once translated into real code

Upvotes: 3

Related Questions