Click here to Skip to main content
15,881,172 members
Please Sign up or sign in to vote.
3.00/5 (2 votes)
See more:
I will start with telling you that I am new to C#. I have a lot of experience with ANSI C.

I have a form that when a button is clicked a test is started and I want to throw away clicks on other buttons. What is happeining is the test is started and while waiting the user presses EXIT. Immediatly when the test is done the form exits and they can not see the results.

I have tried
C#
this.button2.Enabled = false;

and the button is grayed out, but still usable.

I have tried
C#
if (ignoreButton2)
{
    return;
}

in the method and the button is still used.

Is there a simple way to throw away a button?

Here is some simple example code.
C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ButtonTestForm
{
    public partial class Form1 : Form
    {
        int count1 = 0;
        int count2 = 0;

        bool ignoreButton1 = false;
        bool ignoreButton2 = false;

        public Form1()
        {
            InitializeComponent();
            updateLabels();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (ignoreButton1)
            {
                return;
            }
            ignoreButton2 = true;

            this.button2.Enabled = false;
            count1++;
            updateLabels();
            System.Threading.Thread.Sleep(5000);
            this.button2.Enabled = true;

            ignoreButton2 = false;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (ignoreButton2)
            {
                return;
            }
            ignoreButton1 = true;

            count2++;
            updateLabels();
            System.Threading.Thread.Sleep(2000);

            ignoreButton1 = false;
        }

        private void updateLabels()
        {
            label1.Text = "count 1 is " + count1.ToString();
            label2.Text = "count 2 is " + count2.ToString();
        }
    }
}


I can click on button 1 and while sleeping click on button 2. Button 2 is executed after button 1 is finished.
Posted
Updated 26-Apr-12 9:33am
v3
Comments
Sergey Alexandrovich Kryukov 24-Apr-12 11:51am    
What does "thow away a button" means, exactly? You can disable it, hide it, removed permanently (but that will shift the layout somehow). Perhaps, start with your goal and your purpose of "throwing out". Maybe, the problem is your design.

What tells you that if Enables == true, the button is "usable"? It is certainly not?

--SA
[no name] 24-Apr-12 11:51am    
What do mean that the disabled button is still usable? If it's disabled then it can't be clicked on which what I think you want...
The other section just returning from the button click should do what you want too.
What do mean "throw away a button"?
If you just make the button invisible you won't have to worry about a user clicking on it.....
Sergey Alexandrovich Kryukov 24-Apr-12 11:53am    
Yes, I asked same things...
--SA
[no name] 24-Apr-12 11:55am    
We was typing at the same time.
John_Gibbs 24-Apr-12 13:16pm    
I want to gray it out, but not service the click if somebody clicks on it.

Why not set it to Visible = false at the start of the process and then Visible = true at the end? If you wanted to maintain positions then you could replace it with a similarly sized empty graphic of some kind. Just a quick thought.
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 24-Apr-12 11:55am    
Too complex for the purpose and not the best in terms of usability. Usually Enables = false is the best way. You should not buy OP's statement that disabling does not work properly. It actually does...
--SA
R. Giskard Reventlov 24-Apr-12 12:09pm    
Whilst it may be too complex for you it is fairly straightforward and it does address the ops question directly. However, I would agree that enable = false should work: interesting to see why the op thinks it doesn't.
Sergey Alexandrovich Kryukov 25-Apr-12 16:38pm    
Exactly. I don't say your suggestion is complex; it is only overly complex compared with most adequate Enabled = true. You should not buy what OP says. I'm waiting for OP's proof, otherwise there is nothing to talk about.
--SA
R. Giskard Reventlov 25-Apr-12 17:48pm    
I always buy what op says. :-)
Sergey Alexandrovich Kryukov 25-Apr-12 18:09pm    
You are risking to buy a lemon. :-)
--SA
The easyist would be to have a flag (bool) that you set when you enter the event handler, and just check this flag before processing any code in the other event handlers. This is not what I would consider a good solution. A better one would be to disable the buttons and then re-enable after the code finishes.
 
Share this answer
 
Comments
John_Gibbs 24-Apr-12 14:10pm    
I did both of those and neither worked.
Kschuler 24-Apr-12 16:45pm    
Then you may have been doing them wrong. Why not post all of the code that didn't work and we can help you make it work.
Based on the code that you posted, it's easy to see why you are seeing the behavior that you are seeing. The click event for button2 is being processed after button1's click event. That is to say that button2 was enabled when button1's click event finished and button2 was free to process the click. If button2 was not re-enabled within the button1 click event that you would get the behavior you seek.

Just as a test I tried this scenario with the button diabled, igoring the click via a variable and making the button invisible. Oddly enough with the button invisible it still received the mouse click. I even tried removing the click delegate and then reapplying it and nothing "normal" worked.

A possible solution would be to run your test or whatever it is on a background thread and re-enable button2 on the thread completion.
 
Share this answer
 
v2
Comments
John_Gibbs 24-Apr-12 14:13pm    
I think you are the closest to an answer, but I can't help but think there is a simpler solution. Of course maybe a background thread is simple.
[no name] 24-Apr-12 14:30pm    
I could not think of anything based on how your code is setup. A background worker is certainly easier than the alternatives.
If I'm understanding you correctly, I think you're just overthinking it. Create a form level variable that keeps track of whether or not the process is running. When the user attempts to close the form, you can use this variable to see if they should be allowed to close it or not. I use the FormClosing event for this because it covers if the user tried to close the form with a button OR with the little X in the upper right corner. Here is code that I have used in the past (It's VB.Net, but you should be able to convert it pretty easily)
VB
Private Sub Update_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    If boolIsSyncRunning Then
        'Do not let user close window while synchronize is running
        My.Computer.Audio.PlaySystemSound(Media.SystemSounds.Beep)
        e.Cancel = True
    End If
End Sub

You could even put a messagebox inside the If statement and let the user know that they can't close the form at this time, if you wanted.

You could also use this variable to decide if you want to run the code of your buttons or not...but I'd suggest that instead you make sure that when you kick off your process that you also just disable the buttons that aren't supposed to be used. That way the user knows for sure that they aren't available.

Hope this helps.
 
Share this answer
 
First of all, thank you for providing a complete code sample. Well, not quite complete, because you did not show the essential code done by the designer (for code sample you should write that code by yourself and show: adding controls and adding event handlers to invocation lists of event), but anyone can reasonable guess what it its.

Of course you should observe something which can be interpreted as failure to disable a button. When I said that button1.Enabled = false works correctly, I meant the intended use of it, without any tricks which can disrupt behavior not of just feature, but the whole UI behavior. This trick is calling Thread.Sleep. You should never ever call Thread.Sleep in a UI thread.

You re-enable button before you allow the application to run the event loop. To understand what's going on, add one line before that one:

C#
button1.Enabled = false
Application.DoEvents(); //ATTENTION! DON'T DO IT IN REAL APPLICATIONS! THIS IS NOT A SOLUTION.


No, one warning is not enough:
Attention! Don't write the above code in real applications. This is not a solution. Don't call Thread.Sleep in UI thread.

—SA
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900