[英]C# Windows form closing automatically
我有一个 Windows 应用程序,我的第一个 Windows 窗体是登录。 成功登录后,它必须打开“主页”表单。 我在调试时看到“主页”表单,但是一旦代码进入 Home.Designer.cs 中的 Dispose 方法,我的应用程序就会停止。
我的登录页面代码如下所示:
private void loginbtn_Click(object sender, EventArgs e)
{
String username = "admin";
String password = "admin";
String @uname = Unametxtbox.Text;
String @pass = Passtextbox.Text;
if (@uname.Equals(username) && @pass.Equals(password))
{
MessageBox.Show("Login Successful");
Home home = new Home();
home.Show();
this.Close();
}
else
{
MessageBox.Show("Invalid Credentials!");
}
}
我的 Home.cs 页面如下所示:
public partial class Home : Form
{
public Home()
{
InitializeComponent();
}
}
而 Home.Designer.cs 有以下代码:
partial class Home
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Home));
this.label1 = new System.Windows.Forms.Label();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.closebtn = new System.Windows.Forms.PictureBox();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.Storedbtn = new System.Windows.Forms.Button();
this.Soldbtn = new System.Windows.Forms.Button();
this.Transbtn = new System.Windows.Forms.Button();
this.Supbtn = new System.Windows.Forms.Button();
this.Empbtn = new System.Windows.Forms.Button();
this.Custbtn = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.closebtn)).BeginInit();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.PictureBox closebtn;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.Button Storedbtn;
private System.Windows.Forms.Button Soldbtn;
private System.Windows.Forms.Button Transbtn;
private System.Windows.Forms.Button Supbtn;
private System.Windows.Forms.Button Empbtn;
private System.Windows.Forms.Button Custbtn;
}
如果我评论 this.Close(); 在 loginbtn_Click 中,我可以看到 Windows 窗体,但没有关闭 Login Windows 窗体。
我在这里缺少什么,提前致谢。
无需深入挖掘,应用程序的生命周期与 WinForms 中的主窗口相关联。 有些东西可以延长生命周期,例如分离线程,但我不会深入探讨。
在此处的代码中,对this.Close()
的调用有效地终止了应用程序,因为就 Windows 事件循环而言,一旦主窗口消失,您就完成了应用程序。
但是还有另一个问题,即使您没有调用this.Close()
,您也正在创建一个 Home 对象,它位于函数的局部变量中。 一旦到达if
语句的末尾,您对该对象的最后引用就消失了。 当垃圾收集器调用时,它将无法访问您的 Home 对象,这会触发它被销毁和释放。 该对象需要存储在函数调用完成后将持续存在的某个位置。
我使用 WinForms 已经有一段时间了,据我所知,没有真正的方法来处理这样的“页面”。 还有其他框架(例如 WPF)在这方面做得更好。 如果我对 WinForms 处理不当的看法是错误的,也许有人会纠正我。
一种相对简单的方法(使用 WinForms)是使用一个空表单作为应用程序的主页,有一个名为IsMdiContainer
的属性,如果您将其设置为true
,将允许此表单包含其他表单。
在这个主窗口窗体中,我将添加一个函数来加载一个新页面,该页面接受要加载的页面。 它关闭当前页面并打开新页面。 根据您需要在页面之间传递的信息,有多种不同的方法可以做到这一点。 传递信息的粗略但简单的方法是仅将最重要的信息保留在主窗口中,然后孩子们可以访问它,但它确实将您的课程更多地结合在一起。
您不必使用表单或“多文档界面”功能,但我喜欢使用OnLoad
和OnFormClosing
函数。 如果您不需要这些,您可以只为您的页面使用 UserControl,并将IsMdiParent
设置为默认值false
。
您的帖子指出您的目标是首先显示登录表单,在显示主表单之前需要用户凭据。 实现此目的的一种方法是强制创建主窗口句柄,同时通过覆盖SetVisibleCore
防止它变得可见,直到用户成功登录。如果登录被取消(或者用户验证当然失败),则退出应用程序。 通过有效的登录,应用程序继续将HomeForm作为主应用程序窗口。
public partial class HomeForm : Form
{
public HomeForm()
{
InitializeComponent();
// Ordinarily we don't get the handle until
// window is shown. But we want it now.
_ = Handle;
// Call BeginInvoke on the new handle so as not to block the CTor.
BeginInvoke(new Action(()=> execLoginFlow()));
// Ensure final disposal of login form. Failure to properly dispose of window
// handles is the leading cause of the kind of exit hang you describe.
Disposed += (sender, e) => _loginForm.Dispose();
buttonSignOut.Click += (sender, e) => IsLoggedIn = false;
}
private LoginForm _loginForm = new LoginForm();
protected override void SetVisibleCore(bool value) =>
base.SetVisibleCore(value && IsLoggedIn);
bool _isLoggedIn = false;
public bool IsLoggedIn
{
get => _isLoggedIn;
set
{
if (!Equals(_isLoggedIn, value))
{
_isLoggedIn = value;
onIsLoggedInChanged();
}
}
}
private void onIsLoggedInChanged()
{
if (IsLoggedIn)
{
WindowState = FormWindowState.Maximized;
Text = $"Welcome {_loginForm.UserName}";
Visible = true;
}
else execLoginFlow();
}
private void execLoginFlow()
{
Visible = false;
while (!IsLoggedIn)
{
_loginForm.StartPosition = FormStartPosition.CenterScreen;
if (DialogResult.Cancel == _loginForm.ShowDialog(this))
{
switch (MessageBox.Show(
this,
"Invalid Credentials",
"Error",
buttons: MessageBoxButtons.RetryCancel))
{
case DialogResult.Cancel: Application.Exit(); return;
case DialogResult.Retry: break;
}
}
else
{
IsLoggedIn = true;
}
}
}
}
登录表单
public partial class LoginForm : Form
{
public LoginForm()
{
InitializeComponent();
StartPosition = FormStartPosition.Manual;
FormBorderStyle = FormBorderStyle.FixedToolWindow;
textBoxUid.Text = "Admin";
textBoxUid.TextChanged += onOnyTextChanged;
textBoxPswd.TextChanged += onOnyTextChanged;
buttonLogin.Enabled = false;
buttonLogin.Click += (sender, e) => DialogResult = DialogResult.OK;
}
private void onOnyTextChanged(object sender, EventArgs e)
{
buttonLogin.Enabled = !(
(textBoxUid.Text.Length == 0) ||
(textBoxPswd.Text.Length == 0)
);
}
public string UserName => textBoxUid.Text;
protected override void OnVisibleChanged(EventArgs e)
{
base.OnVisibleChanged(e);
if (Visible)
{
textBoxPswd.Clear();
textBoxPswd.PlaceholderText = "********";
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.