代码之家  ›  专栏  ›  技术社区  ›  Rob Bell

如何阻止Windows窗体按钮被单击两次

  •  2
  • Rob Bell  · 技术社区  · 17 年前

    public class SingleClickButton : Button
    {
        protected override void OnClick(EventArgs e)
        {
            bool wasEnabled = this.Enabled;
            this.Enabled = false;
    
            if (wasEnabled)
            {
                base.OnClick(e);
            }
        }
    }
    

    我必须最后调用基本OnClick方法,因为在web请求完成之前,按钮不会禁用。

    我遇到的问题是,如果用户确实点击了多次,点击事件似乎会累积起来,并且仍然会执行。是否有可能取消所有排队的事件?或者,我的问题有更简单的解决方案吗?

    5 回复  |  直到 17 年前
        1
  •  7
  •   TcKs    17 年前

    public class SingleClickButton : Button
    {
            protected override void OnClick(EventArgs e)
            {
                    this.Enabled = false;
                    RunAsynchronousMethod( CallBack );
                    base.OnClick(e);
            }
    
            void CallBack()
            {
                    this.Enabled = true;
            }
    }
    

    “RunAsynchronousMethod”可以创建新的“线程”或使用“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)();
                    }
            }
    }
    
        2
  •  0
  •   sindre j    17 年前

    所以我做了一个小的改变,只忽略后续的点击。

    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;
    }
    
        3
  •  0
  •   Romesh D. Niriella    12 年前

    启用和禁用按钮的问题是,如果单击事件中的内容运行得如此之快,以至于在双击操作的第二次单击之前启用了按钮(一些用户不明白它只需要单击一次),那么这就是我的解决方案。

    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;
      }
    }
    
        4
  •  0
  •   Rafael    11 年前

    我也有类似的问题。通过在表单中添加一个计时器,然后使用该计时器重新启用我在点击事件中禁用的按钮来解决这个问题。

        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;
        }
    

        5
  •  0
  •   mdooney    9 年前

    也许在处理完成之前禁用按钮?