按钮禁用和启用

时间:2012-01-23 17:06:04

标签: vb.net winforms

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

btnGo.Enabled = False

作为第一行和

btnGo.Enabled = True

作为同一方法的最后一行。

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

请建议我做错了什么?

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

6 个答案:

答案 0 :(得分:16)

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

这解释了为什么如果你忘记在事件处理程序方法结束时重新启用按钮控件,它仍然被禁用 - 因为你告诉它在方法的第一行中禁用按钮

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

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

答案 1 :(得分:3)

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

单击按钮,调用BackgroundWorker,如下所示:

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

使用已完成的事件再次启用该按钮:

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

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

我刚刚尝试禁用按钮,Update表单Sleep,然后重新启用它。它仍然执行了点击(在按钮被禁用的情况下“按下”按钮时完成的点击)。

我猜表单“记得”点击。

(编辑:我是用C#做的。)

答案 4 :(得分:0)

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

正如其他人已经建议的那样,解决方案是使用Backgroundworker。

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

答案 5 :(得分:0)

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