Button disable and enable

2020-07-06 03:05发布

I have a vb.net based windows application, where when "GO" button is clicked a bunch of data is loaded into DB. So in my application as soon as "GO" button is clicked I want to just disable it and would like to enable it back when the uploading has completed. Now in my specific method for btnGo_Click() I have:

btnGo.Enabled = False

as first line and

btnGo.Enabled = True

as last line in the same method.

But I fail to understand why the "GO" though appears as being disabled still allows click when processing is going on. Also if I remove the last line, it gets disabled permanently and doesn't allow the click event.

Kindly suggest what am I doing wrong?

Edit (Dated: 25th Jan 2012): I made changes as suggested by our collegues, but I am facing a new issue here. I am facing an issue where the textbox gets updated but not always. I have updated my textbox in "_ProgressChanged" event of the background worker thread. In my case if there is 10 records uploaded. Then there are 10 lines of updates that are expected in the texbox. But only few lines are shown in the textbox. Is it the repaint issue again? Kindly suggest...Because all other things are done as per your suggestion

6条回答
在下西门庆
2楼-- · 2020-07-06 03:29

It's usually not a good idea to manage the state of a submit button. Instead, perform validation on submit.

查看更多
霸刀☆藐视天下
3楼-- · 2020-07-06 03:36

Since you're trying to execute a function that can take some time, I'd advise you to make use of threading. In .NET there's a BackgroundWorker component which is excellent for performing tasks asynchronous.

On button click, invoke the BackgroundWorker like this:

if not bgwWorker.IsBusy then
   btnGo.enabled = false
   bgwWorker.RunWorkerAsync()
end if 

And use the completed event to enable the button again:

Private Sub bgwWorker_DoWork(ByVal sender As System.Object, _
                 ByVal e As System.ComponentModel.DoWorkEventArgs) _
                 Handles bgwWorker.DoWork
' Do your things    
End Sub

Private Sub bgwWorker_RunWorkerCompleted(ByVal sender As System.Object, _
                         ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
                         Handles bgwWorker.RunWorkerCompleted
' Called when the BackgroundWorker is completed.
btnGo.enabled = true
End Sub

In the example above, I've used bgwWorker as the instance of a BackgroundWorker.

查看更多
狗以群分
4楼-- · 2020-07-06 03:38

You're not doing anything wrong. The problem is that the UI doesn't get updated until the code inside of your event handler method finishes executing. Then, the button is disabled and immediately enabled in rapid sequence.

That explains why if you forget to reenable the button control at the end of the event handler method, it is still disabled—because you told it to disable the button in the first line of the method.

This is a classic case of why you should never perform long-running computational tasks inside of an event handler method, because it blocks the UI from being updated. The computation actually needs to happen on a separate thread. But don't try to create the thread manually, and definitely don't try to update your UI from a separate thread. Instead, use the BackgroundWorker component to handle all of this for you automatically. The linked MSDN documentation has a great sample on how to use it.

Disable the button before starting the BackgroundWorker, and then re-enable it in its Completed event, signaling the completion of your database load.

查看更多
够拽才男人
5楼-- · 2020-07-06 03:38

If your btnGo_Click() is ran inside main thread, UI could not be updated correctly inside a time-consuming task.
The best way you can do what you need is running your method in a BackgroundWorker.

查看更多
Summer. ? 凉城
6楼-- · 2020-07-06 03:44

I just tried disabling a button, Updateing the form, Sleeping, and enabling it again. It still performed the click (A click that was done while it "slept" with the button disabled) after it was enabled.

I guess forms "remember" clicks.

(EDIT: I did this in C#.)

查看更多
Rolldiameter
7楼-- · 2020-07-06 03:46

The button click event is handled as soon as the UI thread has idle time. After you disable your button, the UI thread is keept busy by your code. At the end of your method, you re-enable the button, and after that you exit the method and allow for idle time. As a consequence, the button will already be enabled at the point in time where the click event is handled, so your click is "recognized".

The solution is, as others already suggested, to use a Backgroundworker.

Dont try to use doEvents() as a solution (never do), since this would be prone to introduce other subtle problems. That said, you can prove the above explanation with some experimental doEvents in your code. You will see that the click is discarded if a doEvents is performed before the button gets re-enabled. On the other hand, performing a doEvents directly after the button.disable (to "update the GUI") will not help if it is executed before the click.

查看更多
登录 后发表回答