[英]How can I open a WinForm multiple times?
我尝试使用主窗体上的按钮打开第二个窗体,但是当我关闭第二个 window 时,我无法再次打开它。
我在主窗体中添加了以下代码:
settings_window secondForm = new settings_window();
private void settings_button_Click(object sender, EventArgs e)
{
secondForm.Show();
}
但是,当我第二次尝试打开名为 settings_window 的第二个窗体时,出现以下错误:System.ObjectDisposedException。
我找到了以下代码来解决这个问题,但我不知道该把它放在哪里:
private void settings_window_FormClosing(object sender, FormClosingEventArgs e)
{
this.Hide();
e.Cancel = true; // Do not close the form.
}
我认为每次要打开表单时都需要创建一个新的表单实例。 每次单击该按钮时,它都会创建一个新的 settings_window 表单实例。
private void settings_button_Click(object sender, EventArgs e)
{
// Create a new instance of the form
settings_window secondForm = new settings_window();
secondForm.Show();
}
您可以避免存储 Forms 的引用,并使用一个简单的通用方法,当它的一个实例已经存在时显示一个表单,或者在之前没有创建一个实例时创建一个新的(并显示它):
private void ShowForm<T>() where T : Form, new()
{
T? f = Application.OpenForms.OfType<T>().SingleOrDefault();
if (f is null) {
f = new T();
f.FormClosing += F_FormClosing;
}
f.Show();
BeginInvoke(new Action(()=> f.WindowState = FormWindowState.Normal));
void F_FormClosing(object? sender, FormClosingEventArgs e)
{
e.Cancel = true;
(sender as Form)?.Hide();
}
}
当你需要它时,调用ShowForm<SomeFormClass>()
,例如,
ShowForm<settings_window>()
笔记:
FormClosing
事件。BeginInvoke()
用于推迟FormWindowState.Normal
分配。 这仅在最小化窗体的情况下使用,然后右键单击任务栏中的它的图标,然后从菜单中 select Close Windows
。 如果不推迟此分配,最小化的表单将不会再次出现。nullable
(例如,请参阅object? sender
)。 如果 nullable 被禁用或者您的目标是 .NET Framework,请将其删除(例如,更改object sender
) secondForm 是主窗体secondForm
的私有字段吗? 它应该工作。
替代解决方案是将其显示为模态 - ShowDialog()
此外,如果您想在第二个表单中保存一些数据,只需使用构造函数中的一些数据初始化,然后保存到第一个/父表单。
您的代码显示了一个您已命名为settings_window
的 class,这给了我们有关其预期用途的提示。 通常,对于行为“类似于”设置 window 的表单,您可以使用同一实例多次调用,您可以使用此模式声明成员变量:
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
// Provide some means, like a menu or button, to show 'secondForm'
settingsMenu.Click += onClickSettingsMenu;
// Dispose the settings_form when the MainForm does.
Disposed += (sender, e) => secondForm.Dispose();
}
// By instantiating it here, its public default or persisted
// properties are immediately available, for example even
// while the main form constructs and loads the initial view.
settings_window secondForm = new settings_window();
private void onClickSettingsMenu(object? sender, EventArgs e)
{
if(DialogResult.OK.Equals(secondForm.ShowDialog()))
{
// Apply actions using the properties of secondForm
}
}
}
这适用于您想要的任何形式:
GameLevel
、 SortType
等),即使表单当前不可见。 它起作用的原因是调用ShowDialog
(与调用Show
不同)有意不处理 window 句柄,这是为了支持这种情况。 然后,应用程序负责在应用程序关闭时处理资源。
Microsoft 的ShowDialog文档解释了它是如何工作的。
与非模态 forms 不同,当用户单击对话框的关闭窗体按钮或设置 DialogResult 属性的值时,.NET 框架不会调用 Close 方法。 相反,窗体是隐藏的,无需创建对话框的新实例即可再次显示。 因为显示为对话框的窗体是隐藏的而不是关闭的,所以当您的应用程序不再需要该窗体时,您必须调用该窗体的 Dispose 方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.