4

I got two forms, main and second form. Since I want to navigate between them easily, while avoiding creating multiple instances of each, I used this at main form:

Form2 secondForm = new Form2();
private void btnForm2_Click(object sender, EventArgs e)
{
 secondForm.Show(this);
 Hide();
}

and the code below at second form:

private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{ 
 e.cancel = true;
 Owner.Show();
 Hide();
}

Everything works just perfect, except the fact that I can't close the application. When I go to second form and back to main, close button won't work anything at all.

How can I close the program while I still use this code?

I also tried this code to see if close button is working itself:

 private void Form1_FormClosing(object sender, FormClosingEventArgs e)
 {
      MessageBox.Show("Closing");
 } 

MessageBox was shown, but nothing happened after.

Ehsan Sajjad
  • 61,834
  • 16
  • 105
  • 160
farshad
  • 764
  • 10
  • 25

4 Answers4

3

Use

Environment.Exit(0);

to close

Mostafiz
  • 7,243
  • 3
  • 28
  • 42
0

Closing Form1 'tries' to close form2. Runs your Form2_Closing event which cancels the close and runs form1.

Code with unsubsribing to events(quick & dirty), note the internal modifier on Form2. You might consider making stop/start subsribing as methods.

    private void btnForm2_Click(object sender, EventArgs e)
    {

        secondForm.FormClosing += secondForm.Form2_FormClosing;
        secondForm.Show(this);
        Hide();
    }

    internal void Form2_FormClosing(object sender, FormClosingEventArgs e)
    {
        e.Cancel = true;



        FormClosing -= Form2_FormClosing;
        Owner.Show();
        Hide();
    }

After posting this I realised you could use the FormClosingEventArgs.CloseReason property for a simpler solution:

private void Form2_FormClosing(object sender, FormClosingEventArgs e)
    {
        if (e.CloseReason == CloseReason.FormOwnerClosing) { return; }
        e.Cancel = true;
        Owner.Show();
        Hide();


    }
user6144226
  • 613
  • 1
  • 8
  • 15
  • Is there anyway to change Form2_Closing event inside the Form1_Closing event? – farshad Apr 25 '16 at 12:39
  • 1
    You could subsricbe to the event when shown and unsubsricbe from the event when Form2 is closed. – user6144226 Apr 25 '16 at 12:42
  • It looks like the answer I'm looking for,Can you please write an example of the code? – farshad Apr 25 '16 at 12:45
  • You suggestion works great. This code you wrote is the exact answer I was after: `if (e.CloseReason != CloseReason.FormOwnerClosing) { e.Cancel = true; Owner.Show(); Hide(); }` Can you please edit the answer so it will be at the top? – farshad Apr 25 '16 at 13:13
0

This happen because the second Form is not closed - you use e.cancel = true on it. Add the folowing line if you want to force closure of all application windows

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
 {
     System.Windows.Forms.Application.Exit();
 } 

then in form2, you can check if close is directed from user or from Application:

void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
 //close button click by user on form 2
    if(e.CloseReason == CloseReason.UserClosing)
        e.cancel = true //cancel event
   else
     e.cancel = false //close this form
}

Or you can use CloseReason.UserClosing to direct your cancellation depending on parentship. For example:

 void Form2_FormClosing(object sender, FormClosingEventArgs e)
    {

//check if closing signal is from parent
       if   (e.CloseReason == CloseReason.UserClosing.FormOwnerClosing)
         e.cancel = false //close this form
      else 
          e.cancel = true 
    }
christian mini
  • 1,662
  • 20
  • 39
0

I prefer simple solutions.

In Form1_FormClosing use:

secondForm.Close();

And here is the punch line. In Form2_FormClosing wrap the code you already have in:

if (this.Visible)
{
    ...
}

And that works for me. When I close the main form it closes, since the Form2 is not visible and knows not to cancel the close.

Since the answer specifying Environment.Exit(0); got upvoted, see winforms - How to properly exit a C# application? - Stack Overflow. It quotes the MSDN saying it is for console applications. I don't see that in the current documentation but it appears to still be relevant. Also see Application.Exit() vs Application.ExitThread() vs Environment.Exit(). The agreement seems to be that of Environment.Exit, Application.ExitTread and Application.Exit, Application.Exit seems to be the best. I however would not use any of them except to abnormally terminate my application, such as in an error.

Community
  • 1
  • 1
Sam Hobbs
  • 2,594
  • 3
  • 21
  • 32
  • People should explain downvotes. My only explanation for the downvotes is that it explains that Environment.Exit(0) is for console applications. If the problem is the reference to the other answer then I can remove the "Since the answer specifying" part; explaining that would be better than anonymously downvoting. – Sam Hobbs Apr 26 '16 at 19:11
  • I don't understand the down votes either. I was about worried about `Invironment.Exit(0)` as well, it works but it's not the normal way to close the application. – farshad Apr 27 '16 at 14:21
  • Do you still prefer the answer that uses CloseReason.UserClosing? I don't understand the problem with this. – Sam Hobbs Apr 27 '16 at 16:41
  • Both ways works well, only difference might be that other way can be used in more different situation. – farshad Apr 27 '16 at 17:33
  • 1
    I suppose it is a matter of personal preference. I personally avoid things like Application.Exit whenever possible, I prefer to have control of what happens when possible. For simple things like this it does not matter but when things get complicated simple solutions often become big problems. – Sam Hobbs Apr 27 '16 at 18:29