winforms C# Windows窗体自动关闭

xdyibdwo  于 2022-12-14  发布在  C#
关注(0)|答案(3)|浏览(347)

我有一个windows应用程序,其中我的第一个windows窗体是Login。成功登录后,它必须打开“Home”窗体。我在调试时看到“Home”窗体,但一旦代码进入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!");
        }
}

My 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;
}

如果我注解这个.Close();在loginbtn_Click中,我可以看到主窗口窗体,但登录窗口窗体没有关闭。
我错过了什么,提前谢谢你.

wfypjpf4

wfypjpf41#

请尝试使用隐藏而不是关闭

Hide();
Home home = new Home();
home.ShowDialog();
Close();

有关详细信息,请访问microsoft offical site

6yjfywim

6yjfywim2#

Edit:问题原因

在不深究的情况下,应用程序的生存期与WinForms中的主窗口紧密相关。有些事情可以延长生存期,比如分离线程,但我不会深入讨论。
在这里的代码中,对this.Close()的调用实际上终止了应用程序,因为就Windows事件循环而言,一旦主窗口消失,应用程序就完成了。
但是还有另一个问题,即使你没有调用this.Close(),你也在创建一个Home对象,它位于函数的一个局部变量中。一旦你到达if语句的末尾,你对该对象的最后一个引用就消失了。当垃圾收集器调用它时,它将不能访问你的Home对象。该对象需要存储在某个地方,以便在函数调用完成后能够持久保存。

溶液

我使用WinForms已经有一段时间了,据我所知,还没有真实的的方法来处理这样的“页面”。有其他的框架,比如WPF,做得更好。如果我对WinForms处理得不好的看法是错误的,也许有人会纠正我。
一种相对简单的方法(使用WinForms)是使用一个空窗体作为应用程序的主页,有一个名为IsMdiContainer的属性,如果将其设置为true,则允许此窗体包含其他窗体。
在这个主窗口窗体中,我将添加一个函数来加载新页面,它接受要加载的页面。它关闭当前页面并打开新页面。根据需要在页面之间传递的信息,有多种不同的方法来实现这一点。传递信息的简单而粗糙的方法是只将最重要的信息保存在主窗口中,那么孩子们就可以访问它,但它确实会将您的类更多地耦合在一起。
您不必使用Forms或“多文档界面”功能,但我希望可以使用OnLoadOnFormClosing函数。如果您不需要这些函数,可以使用UserControl来代替页面,并将IsMdiParent设置为默认值false

zyfwsgd6

zyfwsgd63#

您的帖子声称您的目标是 * 首先 * 显示登录表单,在显示主表单 * 之前 * 需要用户凭据。实现这一目标的一种方法是拦截应用程序主窗口的第一个VisibleChanged事件HomeForm。由于用户尚未登录,HomeForm将隐藏,并且LoginForm将叠加在它留下的矩形上。如果取消登录,则退出应用程序(当然,如果用户验证失败也是如此)。通过有效登录,应用程序将继续以 HomeForm 作为主应用程序窗口。

public partial class HomeForm : Form
{
    public HomeForm()
    {
        InitializeComponent();
        StartPosition = FormStartPosition.CenterScreen;
    }
    public bool IsLoggedIn { get; private set; }
    protected override void OnVisibleChanged(EventArgs e)
    {
        base.OnVisibleChanged(e);
        if (Visible && !IsLoggedIn)
        {
            // Don't block the VisibleChanged event.
            BeginInvoke(new Action(() =>
            {
                execLoginFlow();
            }));
        }
    }
    private void execLoginFlow()
    {
        Visible = false;
        while (!IsLoggedIn)
        {
            using (var loginForm = new LoginForm())
            {
                loginForm.Size = Size;
                loginForm.Location = Location;

                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
                {
                    WindowState = FormWindowState.Maximized;
                    IsLoggedIn = true;
                    Text = $"Welcome {loginForm.UserName}";
                    Visible = true;
                }
            }
        }
    }
}

释放窗口很重要,如果不这样做,可能会导致你所描述的退出挂起。出于这个原因,“* 因为显示为对话框的窗体是隐藏的,而不是关闭的 *”(根据Microsoft),using块确保弹出窗口将正确释放。这应该有助于避免任何退出应用程序的问题。

public partial class LoginForm : Form
{
    public LoginForm()
    {
        InitializeComponent();
        StartPosition = FormStartPosition.Manual;
        FormBorderStyle = FormBorderStyle.FixedToolWindow;
        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;
}

相关问题