为什么form.Close()不能关闭窗体?

10

我有一个按钮点击事件处理程序,伪代码如下:

private void btnSave_Click(object sender, EventArgs e)
{
  if(txt.Text.length == 0)
     this.Close();
  else
     // Do something else

  // Some other code...
}

这只是一些简单的代码,但重点在于,当文本长度为零时,我想关闭表单。但是,代码执行了 // Some other code 部分,而不是关闭表单。在单击事件处理程序完全执行后,然后表单被关闭。

我知道,当我在 this.Close() 后面直接加上 return,表单就会关闭,但我想知道为什么调用 this.Close() 时表单没有直接关闭。为什么事件处理程序的其余部分会被执行?

7个回答

15

因为您没有离开方法,所以事件处理程序的其余部分将被执行。就是这么简单。

调用 this.Close() 并不会立即“删除”窗体(和当前的事件处理程序)。如果没有对该窗体的引用,则稍后垃圾回收器将收集该窗体。

this.Close() 只是一个普通的方法调用,除非该方法抛出异常,否则您仍然处于当前方法的上下文中。


@Rune FS:在这种情况下,闭合形式的目的是什么?有哪些事情不再可能?我无法想象闭合形式意味着什么。 - Martijn
3
@Martijn,这意味着表单已经在视觉上关闭。它不再显示在屏幕上,用户 也无法与其交互。 如果你关闭一个抽屉,你是否希望它被摧毁?或者你只是接受你必须重新打开它才能与抽屉里的物品互动?关闭表单也是一样的。如果您希望与表单上的内容进行交互,则需要重新打开它,但就像抽屉没有被摧毁一样,对于表单也是如此。 - Rune FS
@Rune FS:感谢您进一步的解释。像抽屉的比喻,现在我明白了!再次感谢。 - Martijn
.Close() 不会立即关闭窗体,而是向消息泵发送一条消息,请求在完成所有当前工作后关闭窗体,即在处理完所有其他消息后关闭。 - Kris Vandermotten
@Rune FS,除非表单是模态表单,否则Form.Close 处理该表单。因此,在此之后您无法在任何情况下重新打开它。有Form.Visible来控制此行为(隐藏/显示表单)。这里的重点是,.Close()不会从调用它的部分返回,有几个原因。例如,您可以从另一个表单或类中调用SomeForm.Close()。Close()只是像其他方法一样的方法。如果您想要这样做,必须明确从调用Close()的方法中返回。 - ThunderGr
显示剩余4条评论

6

关闭只是隐藏了表单,表单仍然存在且如果再次显示它,不会接收到另一个Load事件。

要实际从内存中删除它,请使用Dispose()。


5
不,这不正确。Form.Close()将会释放该窗体,也就是调用Dispose方法。 - Dirk Vollmar
1
不完全正确,如果窗体是一个MDI客户端,并且是不可见的,Close方法不会Dispose。或者如果窗体是一个对话框(调用了ShowDialog),它也不会被Dispose。 - vulkanino
当我使用 Dispose() 而不是 Close() 时,其余的代码仍然会被执行。 - Martijn
4
+1. 谢谢,this.Dispose(); this.Close(); 对我很有效 :) - Jack

3
答案很简单,因为您正在执行当前的方法,所以等到您显式返回或当前正在执行的方法抛出异常之前,this.Close() 将被加入队列中。

2

另一种可能的解决方案是,如果您打开了一个新表单并想要关闭当前表单:如果您使用newForm.ShowDialog()而不是newForm.Show(),则在新表单也关闭之前,它不会使用currentForm.Close()关闭当前表单。


1
在使用 this.Close() 关闭表单时,请注意,如果当前表单是使用 f.ShowDialog(); 显示的,则它将返回 DialogResult.Cancel。在对话框表单(被调用者)中,我添加了 this.Close(); this.Dispose(true);。现在这个对话框似乎终于关闭了!\o/ - Junior Mayhé

0
private void btnCloseForm_Click(object sender, EventArgs e)
{
FirstFrm.ActiveForm.Close();
}

如果你想关闭第一个表单并打开第二个表单,请执行以下操作:

private void btnCloseForm_Click(object sender, EventArgs e)
{
FirstFrm.ActiveForm.Close();
}

private void FirstFrm_FormClosed(object sender, FormClosedEventArgs e)
{
SecounfFrm frm = new SecounfFrm ();
frm.ShowDialog();
}

或者你可以像这样做:

private void btnCloseForm_Click(object sender, EventArgs e)
{
this.Hide();
}

private void FirstFrm_VisibleChanged(object sender, EventArgs e)
{
if(this.Visible == false)
{
this.Close();
}
}

private void FirstFrm_FormClosed(object sender, FormClosedEventArgs e)
{
SecounfFrm frm = new SecounfFrm ();
frm.ShowDialog();
}

0

调用MessageBox.Show(frmMain,"a message","a title")会将“TextDialog”窗体添加到应用程序的Application.OpenForms()表单集合中,与frmMain主窗体并排。关闭Messagebox后,它仍然存在。

当发生这种情况并调用OK按钮委托以关闭主窗体时,调用frmMain.Close()将无效,主窗体不会消失,并且程序不会像通常在退出OK委托后那样终止。只有Application.Exit()才能关闭所有垃圾消息框“TextDialog”。


0

除非表单是模态表单(使用.ShowDialog()打开),Form.Close()也会处理该表单。因此,在此之后,无论其他人说什么,您都无法在任何情况下重新打开它。对于此行为(隐藏/显示表单),有Form.Visible。

这里的重点是,.Close()不会由于多种原因从调用它的部分返回。例如,您可以从另一个表单或类中调用SomeForm.Close()。

Close()只是像其他方法一样的方法。如果您想要这样做,必须明确从调用Close()的方法返回。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接