我在表单上有一个提交Web请求的Windows窗体按钮。我希望能够在第一次单击时禁用该按钮,然后在收到响应时重新启用它。我没有太多控制被调用的代码以及如何调用它所以我可以使用的是Button事件,或者我可以创建自己的按钮,继承自Button,如下所示:
public class SingleClickButton : Button
{
protected override void OnClick(EventArgs e)
{
bool wasEnabled = this.Enabled;
this.Enabled = false;
if (wasEnabled)
{
base.OnClick(e);
}
}
}
我必须最后调用基本OnClick方法,因为在Web请求完成之前按钮不会被禁用。
我遇到的问题是,如果用户多次单击,则单击事件似乎会累积并且仍然执行。有没有办法取消所有排队的活动?或者我的问题有一个更简单的解决方案吗?
答案 0 :(得分:7)
您需要使用此方案:
public class SingleClickButton : Button
{
protected override void OnClick(EventArgs e)
{
this.Enabled = false;
RunAsynchronousMethod( CallBack );
base.OnClick(e);
}
void CallBack()
{
this.Enabled = true;
}
}
“RunAsynchronousMethod”可以创建新的“Thread”或使用“ThreadPool.QueueUserWorkItem”。
修改强>
public class SingleClickButton : Button {
protected override void OnClick(EventArgs e) {
this.Enabled = false;
RunAsynchronousMethod( CallBack );
base.OnClick(e);
}
void CallBack() {
this.Enabled = true;
}
void RunAsynchronousMethod( Action callBack ) {
// there you can use ThreadPool or Thread
ThreadPool.QueueUserWorkItem( this.Worker, callBack );
}
void Worker( object callBack ) {
try {
// some operations
}
finally {
// after operations was proceeded, the callback function will
// be called
((Action)callBack)();
}
}
}
答案 1 :(得分:0)
我有类似的问题。通过向表单添加一个计时器来解决它,然后使用该计时器重新启用我在单击事件上禁用的按钮。
private void btnPrintReport_Click(object sender, EventArgs e)
{
btnPrintReport.Enabled = false;
timerEnablePrint.Enabled = true;
BackgroundProcess.Add("Printing", new WaitCallback(generateReport), null);
}
private void timerEnablePrint_Tick(object sender, EventArgs e)
{
btnPrintReport.Enabled = true;
timerEnablePrint.Enabled = false;
}
将计时器设置为合理的间隔。我使用4秒(这只是为了避免用户双击)
答案 2 :(得分:0)
也许在处理完成之前禁用按钮?
答案 3 :(得分:0)
首先,我实施了@TcKs答案,这对我有很大帮助,但“灰色按钮”给我带来了一些问题。 (有些用户认为系统有问题) 所以我做了一个小改动,只忽略后续点击。
bool ignoreClick = false;
protected override void OnClick(EventArgs e)
{
// Prevent DoubleClick
if (ignoreClick) return;
ignoreClick = true;
ThreadPool.QueueUserWorkItem(this.Worker);
base.OnClick(e);
}
void Worker(object obj)
{
try
{
Thread.Sleep(300);
}
catch { }
ignoreClick = false;
}
答案 4 :(得分:0)
启用和禁用按钮的问题在于,如果点击事件中的内容运行得如此之快,以至于在第二次单击双击操作之前启用了按钮(某些用户不理解它只是需要点击1次)所以这是我的解决方案。
private const int waittime = 2;
private DateTime clickTime = DateTime.Now;
private void cmd_TimeStamp_Click(object sender, EventArgs e)
{
if ((DateTime.Now - clickTime).Seconds < waittime)
return;
else
clickTime = DateTime.Now;
try
{
cmd_TimeStamp.Enabled = false;
//Do some stuff in here
}
catch (Exception ex)
{
//Show error if any
MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
cmd_TimeStamp.Enabled = true;
}
}