0

I have this code:

private void btnAddDataToCSV_Click(object sender, EventArgs e)
{
    var myProcess = new Process();
    this.Enabled = false;
    myProcess.EnableRaisingEvents = true;
    myProcess.Exited += new EventHandler(Excel_Exit);
    myProcess.StartInfo.FileName = "D:\\MyCsvFile.csv";
    myProcess.Start();     
}

public void Excel_Exit(object sender, System.EventArgs e)
{
    MessageBox.Show("Success!!");
    this.Enabled = true;
}

The code works as far as graying out all the buttons on my C# user form and opening the csv file in Excel. When I close Excel the exit event fires displaying a message "Success!!" But it doesn't re-enable the buttons after closing Excel.

I am getting the error

An unhandled exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll

on the this.Enabled = true; line.

As you can see from my comments below. I have now come to to realization that I cannot figure out how to disable even a single button.

private void btnAddDataToCSV_Click(object sender, EventArgs e)
{
    var myProcess = new Process();
    button1.Enabled = false;
    myProcess.EnableRaisingEvents = true;
    myProcess.Exited += new EventHandler(Excel_Exit);
    myProcess.StartInfo.FileName = "D:\\MyCsvFile.csv";
    myProcess.Start();     
}

public void Excel_Exit(object sender, System.EventArgs e)
{
    button1.Enabled = true;
}

The event is firing because the code below works... (displays success!!)

private void btnAddDataToCSV_Click(object sender, EventArgs e)
{
    var myProcess = new Process();
    myProcess.EnableRaisingEvents = true;
    myProcess.Exited += new EventHandler(Excel_Exit);
    myProcess.StartInfo.FileName = "D:\\MyCsvFile.csv";
    myProcess.Start();     
}

public void Excel_Exit(object sender, System.EventArgs e)
{
    MessageBox.Show("Success!!");
}

Any help would be greatly appreciated.

XCELLGUY
  • 179
  • 2
  • 12
  • Never had question that didn't get 10 responses in 10 minutes... Either I have managed to ask a really stupid question, or a really hard question. – XCELLGUY Aug 11 '20 at 18:53
  • i think, `Excel_Exit` method is raised by Process class, but not by button click, so it will not have any information about which button we are talking about. that is why System.InvalidOperationException is raised. – Paramjot Singh Aug 11 '20 at 19:07
  • there could be a better way to fix this, but if we have only static single button, we can mention it ID to change its state. – Paramjot Singh Aug 11 '20 at 19:10
  • I should note... that if i delete "this.Enabled = true;"... there are no errors... meaning the message "Success!!" displays... So it is firing... So I don't think it is related to the "button click" vs "Process class" – XCELLGUY Aug 11 '20 at 19:13
  • while displaying Message, we have specifically mentioned about, in which Message Box we want to show the message. But while enabling the button, we just referenced it with "this" keyword. which in current instance points to the caller object, which is of Process class. – Paramjot Singh Aug 11 '20 at 19:19
  • I think I understand... I eventually will have lots of buttons and such... I was hoping for something more elegant than naming each one. I have also seen "For each" loops that cycle through all the controls... But again... In the interest of a more elegant solution. If my form is called "Form1"... can I simply change "this.Enabled = true" to "Form1.Enabled = true"? – XCELLGUY Aug 11 '20 at 19:27
  • I just tried that... That doesn't seem to work either... It throws another (different) error. – XCELLGUY Aug 11 '20 at 19:32
  • I keep reading that I can put all the controls in a panel. But I tried that too, same result. The controls disable just fine (panel1.Enabled = false;) but I get an error when it tries to enable (panel1.Enabled = true;). – XCELLGUY Aug 12 '20 at 11:40
  • I just tried foreach (Control c in Controls) c.Enabled = false; which I was trying to avoid doing from the beginning but I am getting the same result. It disables the 3 buttons and 2 text boxes and 2 labels that are currently on my form (In the future there will be a lot more). But I get an error when it tries to enable them again using foreach (Control c in Controls) c.Enabled = true; – XCELLGUY Aug 12 '20 at 11:49
  • I just tried to disable a single button "button1.Enabled = false;" and then enable it with "button1.Enabled = true;" and I am having the same problem. – XCELLGUY Aug 12 '20 at 11:55
  • found the exact issue that I am having: https://learn.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls. It says, "You should fix the issue, but you can disable the exception by setting the Control.CheckForIllegalCrossThreadCalls property to false." I haven't finished reading the article yet to see if I can understand how to "fix" it. – XCELLGUY Aug 12 '20 at 13:55
  • 1
    so sorry for a long silence from me. i been reading the same Microsoft Documentation : https://learn.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-make-thread-safe-calls-to-windows-forms-controls. i think i finally came up with the solution. – Paramjot Singh Aug 12 '20 at 17:21

3 Answers3

1

Replace this.Enabled = false; with AddtoCsv.Enabled = false;

private void btnAddDataToCSV_Click(object sender, EventArgs e)
            {
                var myProcess = new Process();
                AddtoCsv.Enabled = false;
                myProcess.EnableRaisingEvents = true;
                myProcess.Exited += new EventHandler(Excel_Exit);
                myProcess.StartInfo.FileName = "E:\\MyCsvFile.csv";
                myProcess.Start();
            }

Just call SetButtonStatemethod inside your Excel_Exit method, and do not forget to declare the delegate.

        public void Excel_Exit(object sender, System.EventArgs e)
        {
            
            // Set Button Enable State True
            SetButtonState();

        }

        private delegate void SafeCallDelegate();
        private void SetButtonState()
        {           

            // check if current thread is same which have created this control
            if (AddtoCsv.InvokeRequired)
            {
                SafeCallDelegate d = new SafeCallDelegate(SetButtonState);                
                AddtoCsv.Invoke(d);                
            }
            else
            {
                AddtoCsv.Enabled = true;
            }
        }
Paramjot Singh
  • 627
  • 4
  • 8
  • CS0103 The name 'AddtoCsv' does not exist in the current context – XCELLGUY Aug 12 '20 at 17:46
  • So close!! Ok... So you called your button 'AddtoCsv'... I called my button 'btnAddDataToCSV'... When I change all the 'AddtoCsv' in your code to 'btnAddDataToCSV'... it works!! But... it is only graying out that single button... I want to gray out everything on the form... the form is called form1... I am going to go try that... – XCELLGUY Aug 12 '20 at 17:50
  • you can get reference for getting all of the form controls into an iterate able list. : https://stackoverflow.com/questions/3419159/how-to-get-all-child-controls-of-a-windows-forms-form-of-a-specific-type-button – Paramjot Singh Aug 12 '20 at 18:13
1

i have added 2 more controls to the form, and set it to disabled on opening of excel file.

private void btnAddDataToCSV_Click(object sender, EventArgs e)
        {
            var myProcess = new Process();
            AddtoCsv.Enabled = false;
            textBox1.Enabled = false;
            checkBox1.Enabled = false;
            myProcess.EnableRaisingEvents = true;
            myProcess.Exited += new EventHandler(Excel_Exit);
            myProcess.StartInfo.FileName = "E:\\MyCsvFile.csv";
            myProcess.Start();
        }

after that, fetched all the controls inside our form and pass it to SetButtonState method.

    public void Excel_Exit(object sender, System.EventArgs e)
    {

        // Set Button Enable State True
        var controls = this.Controls.Cast<Control>();

        foreach (Control ctrl in controls)
        {
            SetButtonState(ctrl);
        }
        
        
    }

SetButtonState wil make call to invoke method of passed control and then we are able to make changes onto control.

    private delegate void SafeCallDelegate(Control control);
    private void SetButtonState(Control control)
    {           

        // check if current thread is same which have created this control
        if (control.InvokeRequired)
        {
            SafeCallDelegate d = new SafeCallDelegate(SetButtonState);
            control.Invoke(d, control);                
        }
        else
        {
            control.Enabled = true;                                       
            
        }
    }
Paramjot Singh
  • 627
  • 4
  • 8
  • This didn't work for me... I disables the controls but doesn't enable them again when I close excel. There were no errors. Also, I am new to C# and I am not familiar with "this.Controls.Cast();" I tried to look it up on google but I couldn't really find anything. Can you point me to somewhere I can read/learn about this? – XCELLGUY Aug 13 '20 at 12:46
  • it is important to disable the controls by specifically mentioning their ids. for getting Forms controls you can have look at this : http://csharphelper.com/blog/2017/03/loop-forms-controls-c/ – Paramjot Singh Aug 13 '20 at 17:20
  • I took a look at it but I don't completely understand. I understand the importance of disabling controls by specifically mentioning their ids. But I still don't understand "this.Controls.Cast();" Also, I did finally get your code to work. It was a silly mistake that I made. I already had another excel workbook open in the background. I am going to mark your answer as the best answer since it is important to disable the controls by specifically mentioning their ids. Thank you so much for your help. – XCELLGUY Aug 14 '20 at 11:57
  • `this.Controls.Cast();` : in this code snippet, `this` points to the current form element we are working on. if you working with VS Community, hover on `this` keyword, you will see name of current form. after that we are getting all of its controls and cast them into list form. you can learn about casting here : https://www.w3schools.com/cs/cs_type_casting.asp . – Paramjot Singh Aug 14 '20 at 18:04
  • Ok... don't know if you are still around but... I ended up using the tabcontrol to make 2 separate tabs. Now I notice that if I enable / disable the tab... everything seems to work as it should... However, if i try to enable a particular button... the button disables but doesn't enable. I think it is because it is nested within the panel. I think I read about a similar situation people talked about with "panels." I will see if I can find that again... But is there a reason I need to disable each control? Instead of just disabling the tab? – XCELLGUY Aug 19 '20 at 00:29
0

Ok... I couldn't get the entire form to disable. But based on other stuff I have found, I created a "panel" and put all my buttons inside the panel and was able to enable the entire panel.

So the solution below works. Special thanks to Paramjot Singh who posted the other solution which works great for a single button, I don't know if I would have figured this out without his help!!

private void btnAddDataToCSV_Click(object sender, EventArgs e)
{
    var myProcess = new Process();
    panel1.Enabled = false;
    myProcess.EnableRaisingEvents = true;
    myProcess.Exited += new EventHandler(Excel_Exit);
    myProcess.StartInfo.FileName = "E:\\MyCsvFile.csv";
    myProcess.Start();
}

public void Excel_Exit(object sender, System.EventArgs e)
{
        
    // Set Button Enable State True
    SetButtonState();

}

private delegate void SafeCallDelegate();
private void SetButtonState()
{           

    // check if current thread is same which have created this control
    if (panel1.InvokeRequired)
    {
        SafeCallDelegate d = new SafeCallDelegate(SetButtonState);                
        panel1.Invoke(d);                
    }
    else
    {
        panel1.Enabled = true;
    }
}
XCELLGUY
  • 179
  • 2
  • 12
  • thank you for your appreciation, i have created a solution that can fetch all of the controls from your form and can change it state. – Paramjot Singh Aug 12 '20 at 18:40