在C#Winform上使用Show Dialog时非常奇怪的错误

我在VS Studio 2008 Express Edition中创建了2个表单,并在main program.cs文件中使用public static声明它们

我只是想用ShowDialog和Close在两个表单之间切换,但是当试图关闭第二个表单并再次使用showdialog打开第一个表单时,它表示当表单已经可见时我不能使用showDialog,而事实并非如此在显示第二个表格之前关闭它。

它让我在使用showdialog之前将form visible属性设置为false,所以我做到了

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

但后来它说我不能使用ShowDialog,因为表格已经在对话模式中显示,我必须关闭它。 所以我做了它所要求的

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

但它仍然假装已经使用ShowDialog打开了表单!

这是我的编程或Winform中的Bug吗?

更新:这是我在第5个答案中发布的整个代码(我想使用showdialog而不是show,因为我可能在后台有第3个表单,我不希望用户访问):

  [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(); } 

我按照建议使用了Hide,但它也不起作用。 这是整个程序,我想要做的很简单:我有两个最初在程序中创建的表单,每个表单上有一个按钮关闭自己并打开另一个。 我将所有逻辑放在program.cs中:

  using System; using System.Windows.Forms; namespace twoforms { static class Program { ///  /// The main entry point for the application. ///  /// 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(); } } } 

这是来自MSDN:

当窗体显示为模式对话框时,单击“关闭”按钮(窗体右上角带有X的按钮)会导致隐藏窗体并将DialogResult属性设置为DialogResult.Cancel。 与无模式窗体不同,当用户单击对话框的关闭窗体按钮或设置DialogResult属性的值时,.NET Framework不会调用Close方法。 相反,表单被隐藏,可以再次显示,而无需创建对话框的新实例。 因为显示为对话框的表单未关闭,所以在应用程序不再需要表单时,必须调用表单的Dispose方法。

所以一旦你使用ShowDialog显示一个表单,你现在要关闭它,只需让它返回DialogResult.Cancel这将隐藏(它仍将在内存中)你的第一个表单。 现在您可以在第二个表单上调用ShowDialog。 再次,如果你想切换到第一个表单然后让第二个表单返回DialogResult.Cancel,现在只需在第一个表单上调用ShowDialog。

这是您程序中的错误。 如果你有一个表单的两个实例(称为A和B),你显然不能使用ShowDialog连续显示另一个。 如果你能做到这一点,那就意味着A以模态方式显示B,然后B然后以模态方式显示A,然后A则以模态方式显示B等。这就像建造一座有两块砖的房子,你只需要继续使用底砖和把它放在另一个上面。

您最好的解决方案是不要将这些表单设置为静态,而只需在需要时创建每个表单的新实例。 您的第二个最佳解决方案是使用Show而不是ShowDialog; 如果您一次只显示其中一个表格,ShowDialog没有任何意义。

静态forms几乎总是一个坏主意(而且我对“差不多”很有礼貌)。 如果您的表单需要很长时间才能创建,那么您应该确定加载和缓存该资源需要花费多长时间作为静态对象,而不是尝试将整个表单缓存为静态。

尝试使用Hide()而不是Close()。 我过去遇到过类似的问题,而Hide()也为我工作过。

我认为你应该像处理方法调用一样对待Modal对话框,并尝试使用Call to ShowDialog的结果来确定下一步要做什么? 如果你需要在对话框之间切换,你应该使用某种结果(也许只是DialogResult看到我的例子)或对话框的公共属性来确定你是否需要显示另一个对话框,如果你需要调用一个modal dialog另一个你应该把它想象成一堆forms,有效地(即使你在调用另一个之前确实让一个看不见)将它们放在另一个上面。 你真的想最大限度地减少这种forms的堆叠。

这是一个人为的例子,但每个表单只有一个按钮,DialogResult设置为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; } } } } 

退出只需单击红色关闭(x)按钮。

查看CloseHide之间的区别。 以及ShowShowDialog之间的区别。

对我来说,你想要实现的目标并不是很清楚; 您只(部分)描述您在代码中所做的事情以及您遇到的问题的症状。 你能描述一下你想做什么吗?

如果您的目标是从主窗口显示两个对话框,其中只有两个中的一个可以同时显示,那么可能有更好的解决方案,而不是使用您使用ShowDialog显示的两个静态(=全局)公共Form实例。

您是否考虑过使用一个对话框Form ,根据具体情况改变它的外观?