tags:

views:

2986

answers:

7

I have created 2 forms in VS Studio 2008 Express Edition and declare them with public static in main program.cs file

I just want to switch between the two forms with ShowDialog and Close but when trying to close the second form and open the first form again with showdialog it says I cannot use showDialog when the form is already visible, whereas it isn't true since I closed it before to show the second form.

It asked me to set the form visible property to false before using showdialog, so I did it

    internal static void CloseSecondForm(FirstForm FirstForm)
    {
        FirstForm .Close();
        SecondForm.Visible = false;
        SecondForm.ShowDialog();
    }

But then it says I cannot use ShowDialog because the form is already shown in Dialog Mode and that I must close it. So I did what it asked

    internal static void CloseSecondForm(FirstForm FirstForm)
    {
        FirstForm .Close();
        SecondForm.Visible = false;
        SecondForm.Close();
        SecondForm.ShowDialog();
    }

But it still pretends that the form is already opened with ShowDialog !

Is this a Bug in my prog or in Winform ?

Update: this is the whole code I posted in 5th answer (I want to use showdialog and not show because I may have a 3rd form in Background that I don't want the user to access):

  [STAThread]
  static void Main()
  {
      Application.EnableVisualStyles();
      Application.SetCompatibleTextRenderingDefault(false);
      Form1 = new Form1();
      Form2 = new Form2();
      Form1.ShowDialog();
      Application.Run();

  }

  // called from Form1 BUTTON
  internal static void ShowForm2(Form1 Form1)
  {
      Form1.Hide();
      Form2.ShowDialog();
  }

  // called from Form2 BUTTON
  internal static void ShowForm1(Form2 Form2)
  {
      Form2.Hide();
      Form1.ShowDialog();
  }
+1  A: 

Try to use Hide() instead of Close(). I had a similar problem in the past and Hide() worked for me.

Freddy
Right: `Close` does extra cleaning duties, while `Hide` basically equates to `Visible=false`.
peSHIr
Thanks I tried with hide without success though see whole code in 5th answer.
programmernovice
A: 

Check out the difference between Close and Hide. And the difference between Show and ShowDialog.

It's not really clear to me what you want to achieve; you only (partially) describe what you done in code and the symptom of the problem you are having. Could you please describe what you are trying to do?

If your goal is to have two dialogs showing from your main window where only one of the two can be visible at the same time, then there are perhaps better solutions than using two static (=global) public Form instances that you show using ShowDialog.

Have you thought of using one dialog Form for this that just changes it appearance depending on the situation?

peSHIr
Have posted the whole program below.
programmernovice
+5  A: 

This is a bug in your program. When you have two instances of a form (call them A and B), you obviously cannot continually show one from the other using ShowDialog. If you could do this, it would mean that A shows B modally, and B then shows A modally, and A then shows B modally etc. This would be like building a house with two bricks, where you just keep taking the bottom brick and placing it on top of the other.

Your best solution is to not make these forms static, and instead just create new instances of each form as you need them. Your second-best solution is to use Show instead of ShowDialog; if you only have one of these forms showing at a time anyway, ShowDialog has no purpose.

Static forms are almost always a bad idea (and I'm being polite about "almost"). If your forms are taking a long time to create, you should identify what resource is taking so long to load and cache that as a static object, instead of trying to cache the entire form as static.

MusiGenesis
Why since I first close the form ? I want to use ShowDialog because it is a blocking window, I may have a third form in background I don't want the user to access.
programmernovice
I can do that in VB or VBA why can't I do that in C# ?
programmernovice
It doesn't matter that you're closing the first form. Because you're showing the second form from the first, the first is kept "alive" no matter what you do.
MusiGenesis
I don't think you can do this in VB or VBA. If you can, it means that ShowDialog doesn't work the same there.
MusiGenesis
Also, if you have a third form in the background, then just make sure the code that shows the other two forms (A and B) is called from the third form (instead of from either A or B).
MusiGenesis
The key to understanding the problem is that ShowDialog is a blocking call, meaning the button handler is never able to complete, and the window never completes closing. If ShowDialog is not a blocking call in VBA then my memory must be leaving me.
AaronLS
@aaronls: I used Visual Basic for more than 10 years. ShowDialog was always a blocking call.
MusiGenesis
I might argue that the _best_ approach is to create two UserControls and show them in the same form. This would nicely work around the problem the questioner will run into re: where his new form pops up on the screen.
Greg D
@Greg: I think the best approach is to just use your forms in the normal way - when you need to show a form, create a new instance and then show it with ShowDialog.
MusiGenesis
A: 

I tried with Hide as suggested but it doesn't work either. This is the whole program, what I want to do is very simple: I have two forms initially created in program with one button on each form to close self and open the other. I put all the logic in program.cs below:

  using System;
  using System.Windows.Forms;

  namespace twoforms
  {
      static class Program
      {
          /// <summary>
          /// The main entry point for the application.
          /// </summary>
          /// 
          public static Form1 Form1;
          public static Form2 Form2;

          [STAThread]
          static void Main()
          {
              Application.EnableVisualStyles();
              Application.SetCompatibleTextRenderingDefault(false);
              Form1 = new Form1();
              Form2 = new Form2();
              Form1.ShowDialog();
              Application.Run();

          }

          // called from Form1 BUTTON
          internal static void ShowForm2(Form1 Form1)
          {
              Form1.Hide();
              Form2.ShowDialog();
          }

          // called from Form2 BUTTON
          internal static void ShowForm1(Form2 Form2)
          {
              Form2.Hide();
              Form1.ShowDialog();
          }
      }
  }
programmernovice
First, "public static Form1 Form1;" should be "public static Form1 form1;" or else things are gonna get REALLY confused.Second in ShowForm2, Form1.Hide() refers to the parameter Form1, but Form2.ShowDialog() refers to the static class variable. You probably shouldn't be passing Form1 in as a parameter there since it's already available as a class variable and this will confused things. Again the parameter name should be lowerCamelCase or else you can't tell when Form1 refers to the class or a variable.
AaronLS
A: 

OK I think I will have to use Show instead of ShowDialog as MusiGenesis suggested but still I am forced to do this just because of technical difficulty not because it suits my user requirements.

Because what if I have a 3rd form in Background I don't want the user to touch if I don't use ShowDialog with the first two forms ?

programmernovice
You should use comments for responses like this.
AaronLS
+1  A: 

I think you should really treat Modal dialogs like method calls, and try to use the result of the Call to ShowDialog to determine what you want to do next? if you have a requirement to switch between dialogs you should use some sort of result (Maybe simply DialogResult see my example) or a public property of the dialog to determine if you need to Show another dialog, If you need to call one modal dialog from another you should think of it like a stack of forms, that effectively (even if you do make one invisible before calling another) place one upon the other. You really want to minimise this stacking of forms.

This is a bit of a contrived example but each form here simply has a single button with DialogResult set to OK.

[STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        bool exit = false;
        while (true)
        {
            if (exit) break;
            using (Form1 frm = new Form1())
            {
                switch(frm.ShowDialog())
                {
                    case DialogResult.OK:
                        break;
                    default:
                        exit = true;
                        break;
                }   
            }
            if(exit) break;
            using (Form2 frm = new Form2())
            {
                switch(frm.ShowDialog())
                {
                    case DialogResult.OK:
                        break;
                    default:
                        exit = true;
                        break;
                } 
            }

        }

    }

to exit simply click the red close (x) button.

Dog Ears
Of course you could have just one instance of each Form "new'd" before the while loop and dispense with the using statements and repeatedly show the same instances of the two forms.
Dog Ears
This would be the same concept as a Window/State manager. The form would notify it's creating class, telling it what button was clicked by setting a variable. After the form has closed, the window manager handles the request.
AaronLS
Wow thank you, will try to look at this thorougly.
programmernovice
+1  A: 

This is from MSDN:

When a form is displayed as a modal dialog box, clicking the Close button (the button with an X at the upper-right corner of the form) causes the form to be hidden and the DialogResult property to be set to DialogResult.Cancel. Unlike modeless forms, the Close method is not called by the .NET Framework when the user clicks the close form button of a dialog box or sets the value of the DialogResult property. Instead the form is hidden and can be shown again without creating a new instance of the dialog box. Because a form displayed as a dialog box is not closed, you must call the Dispose method of the form when the form is no longer needed by your application.

So once you show a form using ShowDialog and you now want to close it, just let it return DialogResult.Cancel This will hide (it will still be in memory) your first form. Now you can call ShowDialog on your second form. Again, if you want to switch to first form then let the second form return DialogResult.Cancel and now just call ShowDialog on first form.

P.K
Thanks will try
programmernovice