winforms 如何多次打开WinForm?

t3irkdon  于 2023-01-05  发布在  其他
关注(0)|答案(4)|浏览(195)

我尝试使用主窗体上的按钮打开第二个窗体,但当我关闭第二个窗口时,无法再次打开它。
我在主窗体中添加了以下代码:

settings_window secondForm = new settings_window();
private void settings_button_Click(object sender, EventArgs e)
{
    secondForm.Show();
}

但是当我第二次尝试打开名为settings_window的第二个窗体时,我得到了以下错误:系统.对象处置异常。
我发现下面的代码来修复这个问题,但我不知道在哪里放置它:

private void settings_window_FormClosing(object sender, FormClosingEventArgs e)
{
    this.Hide();
    e.Cancel = true;    // Do not close the form.
}
5lhxktic

5lhxktic1#

我认为你需要在每次打开窗体时创建一个新的窗体示例,每次点击按钮时都会创建一个新的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();
}
r1wp621o

r1wp621o2#

您可以避免存储窗体的引用,而使用一个简单的泛型方法,该方法在窗体示例已经存在时显示窗体,或者在以前没有创建窗体示例时创建一个新窗体(并显示窗体):

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的分配。这仅用于最小化窗体,然后在任务栏中右键单击其图标并从菜单中选择Close Windows。如果不延迟此分配,最小化的窗体将不会再次显示。
  • 当起始窗体关闭时,所有其他窗体也将关闭
  • 这段代码假设nullable是启用的(例如,参见object? sender)。如果nullable是禁用的,或者您的目标是. NET Framework,请将其删除(例如,在object sender中进行更改)
7uzetpgm

7uzetpgm3#

secondForm是主窗体类的私有字段吗?应该可以。
另一种解决方案是将其显示为modal -ShowDialog()
同样,如果你想在第二个窗体中保存一些数据,只需从构造函数中使用一些数据初始化,然后保存到第一个/父窗体中。

bxpogfeg

bxpogfeg4#

您的代码显示了一个名为settings_window的类,这提示了它的预期用途。
无论如何,通常情况下,您可以为Form类(如settings_window)声明一个 member 字段或属性,然后使用同一示例多次调用ShowDialog。这适用于您希望能够执行以下操作的任何表单:

  • 重复显示和隐藏表单(例如,用户可以多次更改选项的“设置”表单)。
  • 从一开始就检索表单的默认或持久化属性 * 即使从未显示过 *。
  • 在应用运行时的任何给定时刻使用表单的公共属性(例如GameLevelSortType等),即使表单当前不可见。

其工作原理是调用ShowDialog(与调用Show不同)故意不释放窗口句柄,这是为了支持这种场景。应用关闭时,应用负责释放资源。

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();
        // Provide some means, like a menu or button, to show the 'settings_window'
        settingsMenu.Click += onClickSettingsMenu;
        // Dispose the SettingsForm when the MainForm does.
        Disposed += (sender, e) => _settings.Dispose();
    }
    // By instantiating it here, its public default or 
    // persisted properties are immediately available, 
    // for example even the main form is constructing
    // and loading the initial view.
    settings_window _settings = new settings_window();
}

ShowDialog的Microsoft文档解释了其工作原理。
当窗体显示为模式对话框时,单击“关闭”按钮(窗体右上角带有X的按钮)会导致窗体隐藏,并将DialogResult属性设置为DialogResult.Cancel。与非模态窗体不同,当用户单击对话框的关闭窗体按钮或设置DialogResult属性的值时,.NET Framework不调用Close方法。相反,窗体将隐藏,并且无需创建对话框的新示例即可再次显示。由于显示为对话框的窗体是隐藏的而不是关闭的,因此当应用程序不再需要该窗体时,必须调用该窗体的Dispose方法。

相关问题