在 C# Winform 上使用 Show Dialog 时非常奇怪的错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1218517/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Very strange bug when using Show Dialog on C# Winform
提问by programmernovice
I have created 2 forms in VS Studio 2008 Express Edition and declare them with public static in main program.cs file
我在 VS Studio 2008 Express Edition 中创建了 2 个表单,并在 main program.cs 文件中使用 public static 声明它们
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.
我只想使用 ShowDialog 和 Close 在两个表单之间切换,但是当尝试关闭第二个表单并使用 showdialog 再次打开第一个表单时,它说当表单已经可见时我不能使用 showDialog,而事实并非如此,因为我之前关闭它以显示第二种形式。
It asked me to set the form visible property to false before using showdialog, so I did it
它要求我在使用 showdialog 之前将表单可见属性设置为 false,所以我做到了
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
但是后来它说我不能使用 ShowDialog 因为表单已经在对话框模式下显示,我必须关闭它。所以我做了它所要求的
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 !
但它仍然假装表单已经用 ShowDialog 打开了!
Is this a Bug in my prog or in Winform ?
这是我的程序或 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):
更新:这是我在第 5 个答案中发布的完整代码(我想使用 showdialog 而不是显示,因为我可能在后台有第三个表单,我不希望用户访问):
[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();
}
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:
我按照建议尝试使用隐藏,但它也不起作用。这是整个程序,我想做的很简单:我最初在程序中创建了两个表单,每个表单上都有一个按钮来关闭自己并打开另一个。我将所有逻辑放在下面的 program.cs 中:
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();
}
}
}
采纳答案by P.K
This is from MSDN:
这是来自 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.
当窗体显示为模式对话框时,单击关闭按钮(窗体右上角带有 X 的按钮)会导致隐藏窗体并将 DialogResult 属性设置为 DialogResult.Cancel。与无模式窗体不同,当用户单击对话框的关闭窗体按钮或设置 DialogResult 属性的值时,.NET Framework 不会调用 Close 方法。相反,窗体被隐藏,可以再次显示,而无需创建对话框的新实例。因为显示为对话框的表单没有关闭,所以当您的应用程序不再需要该表单时,您必须调用该表单的 Dispose 方法。
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.
因此,一旦您使用 ShowDialog 显示一个表单并且您现在想要关闭它,只需让它返回 DialogResult.Cancel 这将隐藏(它仍将在内存中)您的第一个表单。现在您可以在第二个表单上调用 ShowDialog。同样,如果您想切换到第一个表单,那么让第二个表单返回 DialogResult.Cancel,现在只需在第一个表单上调用 ShowDialog。
回答by Freddy
Try to use Hide() instead of Close(). I had a similar problem in the past and Hide() worked for me.
尝试使用 Hide() 而不是 Close()。我过去遇到过类似的问题,Hide() 对我有用。
回答by peSHIr
Check out the difference between Close
and Hide
. And the difference between Show
and ShowDialog
.
查看Close
和之间的区别Hide
。之间的差异Show
和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
.
如果您的目标是在主窗口中显示两个对话框,其中两个对话框中只能同时可见,那么可能有比使用两个静态(=全局)公共Form
实例更好的解决方案,您使用ShowDialog
.
Have you thought of using one dialog Form
for this that just changes it appearance depending on the situation?
你有没有想过使用一个对话框Form
来根据情况改变它的外观?
回答by MusiGenesis
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.
这是您程序中的错误。当您有一个窗体的两个实例(称为 A 和 B)时,您显然不能使用 ShowDialog 连续显示另一个实例。如果你能做到这一点,那就意味着 A 以模态显示 B,然后 B 以模态显示 A,然后 A 以模态显示 B 等等。这就像用两块砖盖房子一样,你只需要继续拿底部的砖块,然后把它放在另一个上面。
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.
最好的解决方案是不要将这些表单设为静态,而是根据需要创建每个表单的新实例。您的第二个最佳解决方案是使用 Show 而不是 ShowDialog;如果您一次只显示其中一种表单,则 ShowDialog 没有任何意义。
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.
静态形式几乎总是一个坏主意(我对“几乎”很有礼貌)。如果您的表单需要很长时间来创建,您应该确定哪些资源需要花费这么长时间来加载并将其缓存为静态对象,而不是尝试将整个表单缓存为静态。
回答by Dog Ears
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.
我认为你真的应该像对待方法调用一样对待 Modal 对话框,并尝试使用 Call to ShowDialog 的结果来确定下一步要做什么?如果您需要在对话框之间切换,您应该使用某种结果(也许只是 DialogResult 参见我的示例)或对话框的公共属性来确定是否需要显示另一个对话框,如果您需要从另一个你应该把它想象成一堆表格,有效地(即使你在调用另一个之前使一个不可见)将一个放在另一个上。你真的想尽量减少这种形式的堆叠。
This is a bit of a contrived example but each form here simply has a single button with DialogResult set to OK.
这是一个有点人为的例子,但这里的每个表单只有一个按钮,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;
}
}
}
}
to exit simply click the red close (x) button.
要退出,只需单击红色关闭 (x) 按钮。