c#打开一个新窗体,然后关闭当前窗体?
问题的原因:当在主窗体中打开一个子窗体,在关闭子窗体时,主窗体也会关闭。这是因为在子窗体的关闭事件中没有正确处理主窗体的关闭操作。
解决方法:在主窗体中的关闭事件中,需要将子窗体的关闭操作单独处理,以保证在关闭子窗体时不会关闭主窗体。
以下是解决方法的示例代码:
private void ChildForm_FormClosing(object sender, FormClosingEventArgs e) { e.Cancel = true; // 取消子窗体的关闭操作 this.Hide(); // 隐藏子窗体 }
通过在子窗体的关闭事件中取消关闭操作,并隐藏子窗体,可以避免关闭主窗体。
感谢Nihique提供的方法,该方法可以解决这个问题,并且在VS 2015中有效。
C#中打开一个新窗体,然后关闭当前窗体的问题是很常见的。解决这个问题有多种方法,但是其中很多方法要么使用ShowDialog()
,要么是让form1
保持打开但是隐藏。我认为最好最直观的方法是先关闭form1
,然后从外部位置创建form2
(即不在这两个窗体内部创建)。如果form1
是在Main
方法中创建的,那么form2
可以通过使用Application.Run
来创建,就像之前创建form1
一样。下面是一个示例场景:
我需要用户输入凭据,以便我以某种方式对其进行身份验证。之后,如果验证成功,我想向用户显示主程序。为了实现这个目标,我使用了两个窗体:LoginForm
和MainForm
。 LoginForm
有一个标志,用于确定是否成功进行身份验证。然后使用该标志来决定是否创建MainForm
实例。这两个窗体都不需要了解对方的存在,并且两个窗体都可以优雅地打开和关闭。下面是实现这个功能的代码:
class LoginForm : Form { public bool UserSuccessfullyAuthenticated { get; private set; } void LoginButton_Click(object s, EventArgs e) { if(AuthenticateUser(/* ... */)) { UserSuccessfullyAuthenticated = true; Close(); } } } static class Program { [STAThread] static void Main() { LoginForm loginForm = new LoginForm(); Application.Run(loginForm); if(loginForm.UserSuccessfullyAuthenticated) { // MainForm is defined elsewhere Application.Run(new MainForm()); } } }
这是一个比隐藏窗体更好的方法。当我们使用隐藏窗体来退出应用程序时,仅仅关闭当前窗体是不够的。我们必须使用Application.Exit(0)
等方法。
这个方法很不错,但我认为它只适用于两个窗体。那么如果有多个窗体需要在它们之间切换呢?
这个方法只适用于按顺序运行窗体,不能同时运行或者在其他窗体之上,正如问题中所要求的。不过我不确定为什么这个方法只适用于两个窗体。外部代码可以自由地按顺序生成任意数量的窗体。在外部代码中可以切换它们。它可以在运行登录窗体之前检查一些主窗体的状态(比如loginForm.UserSuccessfullyAuthenticated
),也可以使用全局状态来决定是否重新运行登录窗体,或者运行另一个窗体,或者终止进程。
我喜欢这个方法。它既优雅又简单易行。得票率最高的答案是实现相同目标的一种快速而简单的方法,但是长期来看,它给我带来了处理资源清理等方面的问题。做得好。
问题的原因是当调用`this.Close()`关闭当前窗体时,当前窗体和`form2`一起被销毁。因此,需要隐藏当前窗体并将`form2.Closed`事件设置为调用`this.Close()`。
解决方法如下:
private void OnButton1Click(object sender, EventArgs e) { this.Hide(); var form2 = new Form2(); form2.Closed += (s, args) => this.Close(); form2.Show(); }
在Windows窗体中没有`Closed`事件,应该是`FormClosed`事件。
这个解决方法可行,但实际上不应该使用这种方式在窗体之间切换。
隐藏第一个窗体仍然会占用内存,如何释放这个资源?
`(s, args) => this.Close();`是一个lambda表达式。它在`form2.Closed`事件触发时创建一个"内部"函数,并调用它。`(s, args)`只是lambda表达式的参数名称,对于事件处理程序而言,通常是`object sender, EventArgs e`。因为`Closed`事件委托的签名描述了它们的类型,所以不需要给出类型。这只是一个巧妙的方法,避免在当前函数之外声明整个函数(事件处理程序)来处理`Form2.Closed`事件。
对我来说,这段代码会导致不断循环调用`this.Close()`。
它只是隐藏第一个窗体并打开新的窗体,但不关闭第一个窗体。