vb.net 按钮禁用和启用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8975569/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 15:53:41  来源:igfitidea点击:

Button disable and enable

vb.netwinforms

提问by Justin Samuel

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:

我有一个基于 vb.net 的 Windows 应用程序,当点击“GO”按钮时,一堆数据被加载到数据库中。因此,在我的应用程序中,一旦单击“GO”按钮,我只想禁用它,并希望在上传完成后重新启用它。现在在我的 btnGo_Click() 特定方法中,我有:

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.

但我不明白为什么“GO”虽然显示为被禁用,但在处理过程中仍然允许点击。此外,如果我删除最后一行,它将永久禁用并且不允许单击事件。

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

编辑(日期:2012 年 1 月 25 日):我按照同事的建议进行了更改,但我在这里遇到了一个新问题。我面临一个问题,即文本框会更新但并非总是如此。我已经在后台工作线程的“_ProgressChanged”事件中更新了我的文本框。就我而言,如果上传了 10 条记录。然后有 10 行预期在 texbox 中的更新。但是文本框中只显示了几行。难道又是重绘问题?请建议...因为所有其他事情都是按照您的建议完成的

回答by Cody Gray

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.

你没有做错任何事。问题是在事件处理程序方法中的代码完成执行之前,UI 不会更新。然后,按钮被禁用并立即以快速顺序启用。

That explains why if you forget to reenablethe 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 BackgroundWorkercomponentto handle all of this for you automatically. The linked MSDN documentation has a great sample on how to use it.

这是一个经典案例,说明为什么永远不要在事件处理程序方法内执行长时间运行的计算任务,因为它会阻止 UI 更新。计算实际上需要在单独的线程上进行。但是不要尝试手动创建线程,绝对不要尝试从单独的线程更新您的 UI。相反,使用BackgroundWorker组件为您自动处理所有这些。链接的 MSDN 文档有一个关于如何使用它的很好的示例。

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

在启动之前禁用按钮BackgroundWorker,然后在其Completed事件中重新启用它,表示数据库加载完成。

回答by Rhapsody

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 BackgroundWorkercomponent which is excellent for performing tasks asynchronous.

由于您正在尝试执行一个可能需要一些时间的函数,因此我建议您使用线程。在 .NET 中有一个BackgroundWorker组件,它非常适合异步执行任务。

On button click, invoke the BackgroundWorker like this:

单击按钮时,像这样调用 BackgroundWorker:

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.

在上面的示例中,我使用 bgwWorker 作为 BackgroundWorker 的实例。

回答by ispiro

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.

我只是尝试禁用按钮,Update输入表单,Sleep输入并再次启用它。启用后,它仍然执行单击(在禁用按钮的情况下“休眠”时完成的单击)。

I guess forms "remember" clicks.

我猜表单“记住”点击。

(EDIT: I did this in C#.)

(编辑:我在 C# 中做了这个。)

回答by tdanker

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".

只要 UI 线程有空闲时间,就会处理按钮单击事件。禁用按钮后,UI 线程会因您的代码而忙碌。在您的方法结束时,您重新启用按钮,然后退出该方法并留出空闲时间。因此,按钮将在处理单击事件的时间点被启用,因此您的单击被“识别”。

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.

不要尝试使用 doEvents() 作为解决方案(永远不要这样做),因为这很容易引入其他微妙的问题。也就是说,您可以在代码中使用一些实验性的 doEvents 来证明上述解释。如果在按钮重新启用之前执行了 doEvents,您将看到单击被丢弃。另一方面,如果在单击之前执行 doEvents,则在 button.disable(以“更新 GUI”)之后直接执行 doEvents 将无济于事。

回答by LastTribunal

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

管理提交按钮的状态通常不是一个好主意。相反,在提交时执行验证。

回答by Marco

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.

如果您btnGo_Click()在主线程内运行,则无法在耗时的任务中正确更新 UI。
您可以执行所需操作的最佳方法是在BackgroundWorker 中运行您的方法。