2

I want to prevent the user clicking two times on a button when it has been already executing and the process is not finished.

I am using compact framework 3.5 and I have problems when the user clicks two times on a button that is already executing or some other button. I want to disable all buttons when the program is executing and enable them again when the process is done.

OS: Windows mobile 6.1
Framework: .NET 3.5 CF

Otiel
  • 18,404
  • 16
  • 78
  • 126
senzacionale
  • 20,448
  • 67
  • 204
  • 316
  • 1
    possible duplicate of [how to lock the application GUI in C# Winform](http://stackoverflow.com/questions/6423606/how-to-lock-the-application-gui-in-c-sharp-winform) – Hans Passant Oct 21 '11 at 11:34
  • not true, This is not winfom, it is mobile. Non of solutions works... – senzacionale Oct 21 '11 at 11:44

3 Answers3

3

Try adding this.Enabled = false first thing (this being the form in question) in the scope of your Click handler. Be sure to set it back to true when done. You may need to Application.DoEvents() or Update() to display visible progress if this all in the scope of the handler. Probably the preferred way to do any extended processing though would be to spawn a background thread and update your UI from it using Invoke and BeginInvoke.

Damon8or
  • 527
  • 2
  • 11
2

I found that I needed to do this quite often when building a windows mobile application so made a simple utility class.

public static class FormUtility
{
    /// <summary>
    /// Lock the form whilst processing
    /// </summary>
    /// <param name="controlCollection"></param>
    /// <param name="enabled"></param>
    public static void FormState(Control.ControlCollection controlCollection, bool enabled)
    {
        foreach (Control c in controlCollection)
        {
            c.Enabled = enabled;
            c.Invalidate();
            c.Refresh();
        }
    }
 }

All I need to do was then call one line to lock the form down.

FormUtility.FormState(this.Controls, false);

You should end up with something like

 private void btnSave_Click(object sender, EventArgs e)
 {
      FormUtility.FormState(this.Controls, false);

      //Do your work
      if (!SaveSuccessful())
           //Renable if your validation failed
           FormUtility.FormState(this.Controls, true);
 }

EDIT : I think what @tcarvin is suggesting is that you do not need to call refresh on every control but simply invalidate the controls and then refresh the container which will cause all the invalidated controls to redraw at once. I haven't tested this but a small change to something like...

    public static void FormState(Form form, bool enabled)
    {
        foreach (Control c in form.Controls)
        {
            c.Enabled = enabled;
            c.Invalidate();
        }

        form.Refresh();
    }

Then use

FormUtility.FormState(this, true);
fluent
  • 2,393
  • 4
  • 22
  • 32
  • Did you really find the need for the Refresh on every control? I would think you could send the Refresh to the parent and all of the invalidated controls would be refreshed. – tcarvin Oct 21 '11 at 18:09
  • Yep, good point. Most of my mobile forms are very simple with only a few controls so I never noticed any real performance problems. Thanks for the tip. – fluent Oct 22 '11 at 18:25
  • Thx boath for answer. tcarvin how do you mean by partent? Can you explain me please? – senzacionale Oct 25 '11 at 08:38
  • 1
    Added an alternative using the suggestion from @tcarvin – fluent Oct 25 '11 at 08:47
0

This is the easiest way, for a button called button1:

void button1_Clicked(object sender, EventArgs e) {
  button1.Enabled = false;
  try {
    // put your code here
  } finally {
    button1.Enabled = true;
  }
}