C#打开一个新表格,然后关闭当前表格?


89

例如,假设我处于表格1中,那么我想要:

  1. 打开表格2(通过表格1中的按钮)
  2. 关闭表格1
  3. 专注于表格2

18
糟糕的可用性。如果您使用的是WinForms,则只需创建一个容器窗口,然后替换面板即可。您的用户会为此而爱您(并讨厌您不这样做)
ClausJørgensen

1
听克劳斯!您想要实现的目标可能是:a)像向导一样的一系列步骤的winforms实现,或者b)尝试在“数据输入/提交”表单之后显示“结果”表单。无论是a)还是b),您尝试实现的UI行为都是次优的解决方案。
Simen S

非常感谢Clause和SimenS。您的评论对像我这样的初学者很有帮助。我将阅读有关GUI和可用性的更多教程。你能推荐一些有用的东西吗?
tnhan07 2011年


如果您真正的意图只是使用登录(或类似方式)表格,也请检查[answers here](stackoverflow.com/questions/4759334/…)。
ilias iliadis

Answers:


193

史蒂夫的解决方案不起作用。调用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();
}

2
点网的Windows窗体中没有Closed事件。您能告诉我这是FormClosed事件吗
Anjali

2
不隐藏第一个表单仍保留它的内存吗?我们如何释放该资源?
user2635088 2015年

5
form2.Closed += (s, args) => this.Close();我可以知道这句话如何工作吗?到底(s,args)是什么?
Yash Saraiya

1
(s, args) => this.Close();是lambda表达式。它创建一个在form2.Closed事件触发时调用的“就地”函数。(s, args)只是lambda参数的名称。对于事件处理程序,通常类似于(object sender, EventArgs e)。因为Closed事件委托人签名描述了它们的类型,所以没有给出类型(如果需要,请有人纠正我的措辞)。//总的来说,这是一种棘手的方法,不必在处理Form2.Closed事件的当前函数之外声明整个函数(事件处理程序)。
KDecker

1
它只是隐藏第一个表格并打开新表格,而不是关闭第一个表格
Uddyan Semwal

25

尝试做这个...

{
    this.Hide();
    Form1 sistema = new Form1();
    sistema.ShowDialog();
    this.Close();
}

这是东西。我有一个主表格。但我使用一个小的表单进行登录。此表单使用此方法调用主表单。好的,我们在这里很好。问题是,当主窗体显示子窗体时,在关闭子窗体时……它也关闭了主窗体。因此,由于我使用的是Nihique发布的方法。该代码一直很好用!...
MontDeska

该代码对我有用。我正在使用
VS2015

21

其他答案已经描述了许多不同的方式。然而,许多人要么参与ShowDialog()form1继续开放,但隐藏。在我看来,最好和最直观的方法是简单地关闭form1然后form2从外部位置创建(即,不是从这两种形式中的任何一种)。在form1中创建的情况下Mainform2可以Application.Runform1以前一样简单地创建。这是一个示例方案:

我需要用户输入其凭据,以便我以某种方式对其进行身份验证。之后,如果身份验证成功,我想向用户显示主应用程序。为了实现这一点,我使用两种形式:LogingFormMainForm。在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)等
Peck_conyon

很好,但我认为仅适合两种形式。那么在它们之间切换多种形式呢?
MAF博士

如操作员要求的那样,这仅限于顺序运行的表单,而不是并行运行或彼此重叠。我不确定为什么将其限制为仅两种形式。外部代码可以按需要随意生成任意多种形式。它们之间的切换也可以通过外部代码来完成。它可以检查主表单上的某些状态(如loginForm.UserSuccessfullyAuthenticated之前),也可以检查全局状态,以决定是否重新运行登录表单,还是运行其他表单,或者终止该过程。
Manuzor

11

该行存在的问题是:

Application.Run(new Form1()); 可能可以在program.cs文件中找到。

此行表明form1将处理消息循环-换句话说,form1负责继续执行您的应用程序-关闭form1时,该应用程序将关闭。

有几种方法可以解决此问题,但是所有一种或另一种方法都不会关闭form1。
(除非我们将项目类型更改为Windows Forms应用程序以外的其他类型)

我认为最适合您的情况是创建3种形式:

  • form1-将保持不可见并充当管理员,您可以根据需要将其分配为处理任务栏图标。

  • form2-将具有按钮,单击该按钮将关闭form2并打开form3

  • form3-将具有需要打开的其他表单的角色。

这是实现此目的的示例代码:(
我还添加了一个示例,以关闭第3种形式的应用程序)

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1()); //set the only message pump to form1.
    }
}


public partial class Form1 : Form
{
    public static Form1 Form1Instance;

    public Form1()
    {
        //Everyone eveywhere in the app should know me as Form1.Form1Instance
        Form1Instance = this;

        //Make sure I am kept hidden
        WindowState = FormWindowState.Minimized;
        ShowInTaskbar = false;
        Visible = false;

        InitializeComponent();

        //Open a managed form - the one the user sees..
        var form2 = new Form2();
        form2.Show();
    }

}

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        var form3 = new Form3(); //create an instance of form 3
        Hide();             //hide me (form2)
        form3.Show();       //show form3
        Close();            //close me (form2), since form1 is the message loop - no problem.
    }
}

public partial class Form3 : Form
{
    public Form3()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Form1.Form1Instance.Close(); //the user want to exit the app - let's close form1.
    }
}


注意:作为行业生产标准,使用面板或动态加载用户控件更具学术性和可取性-但在我看来,您只是想推理事情的方式-为此目的,这个示例更好。

现在已经理解了这些原理,让我们仅用两种形式尝试一下:

  • 与上一个示例一样,第一个表单将充当管理者的角色,但也会显示第一个屏幕-因此,不会隐藏它只是将其关闭。

  • 第二种形式将充当显示下一个屏幕的角色,并且通过单击按钮将关闭应用程序。


    public partial class Form1 : Form
    {
        public static Form1 Form1Instance;

        public Form1()
        {
            //Everyone eveywhere in the app show know me as Form1.Form1Instance
            Form1Instance = this;
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //Make sure I am kept hidden
            WindowState = FormWindowState.Minimized;
            ShowInTaskbar = false;
            Visible = false;

            //Open another form 
            var form2 = new Form2
            {
                //since we open it from a minimezed window - it will not be focused unless we put it as TopMost.
                TopMost = true
            };
            form2.Show();
            //now that that it is topmost and shown - we want to set its behavior to be normal window again.
            form2.TopMost = false; 
        }
    }

    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form1.Form1Instance.Close();
        }
    }

如果您更改了前面的示例,请从项目中删除form3。

祝好运。


6

您不是很特定,但是您似乎在尝试执行我在Win Forms应用程序中所做的事情:从“登录”表单开始,然后在成功登录后关闭该表单,然后将注意力集中在“主”表单上。这是我的方法:

  1. 使frmMain为启动表单;这是我的Program.cs的样子:

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new frmMain());
    }
    
  2. 在我的frmLogin中,创建一个公共属性,该公共属性被初始化为false,并且仅在成功登录后才设置为true:

    public bool IsLoggedIn { get; set; }
    
  3. 我的frmMain看起来像这样:

    private void frmMain_Load(object sender, EventArgs e)
    {
        frmLogin frm = new frmLogin();
        frm.IsLoggedIn = false;
        frm.ShowDialog();
    
        if (!frm.IsLoggedIn)
        {
            this.Close();
            Application.Exit();
            return;
        }
    

没有成功登录?退出应用程序。否则,请使用frmMain。由于它是启动表单,因此在关闭时,应用程序结束。


3

在您的form1中使用此代码段。

public static void ThreadProc()
{
Application.Run(new Form());
}

private void button1_Click(object sender, EventArgs e)
{
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(ThreadProc));
t.Start();
this.Close();
}

我从这里得到的


请注意,不鼓励仅链接的答案,因此,SO答案应该是搜索解决方案的终点(与引用的另一种中途停留相比,随着时间的流逝,它们往往会过时)。请考虑在此处添加独立的摘要,并保留该链接作为参考。
kleopatra

2

如果您有两种形式:frm_form1和frm_form2。以下代码用于打开frm_form2和关闭frm_form1。(对于Windows窗体应用程序)

        this.Hide();//Hide the 'current' form, i.e frm_form1 
        //show another form ( frm_form2 )   
        frm_form2 frm = new frm_form2();
        frm.ShowDialog();
        //Close the form.(frm_form1)
        this.Close();

1

我通常这样做是为了在表单之间来回切换。

首先,在程序文件中,保留ApplicationContext并添加一个辅助程序SwitchMainForm方法。

        static class Program
{
    public static ApplicationContext AppContext { get;  set; }


    static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);

        //Save app context
        Program.AppContext = new ApplicationContext(new LoginForm());
        Application.Run(AppContext);
    }

    //helper method to switch forms
      public static void SwitchMainForm(Form newForm)
    {
        var oldMainForm = AppContext.MainForm;
        AppContext.MainForm = newForm;
        oldMainForm?.Close();
        newForm.Show();
    }


}

然后,在代码中的任何位置,我现在都调用SwitchMainForm方法以轻松切换到新表单。

// switch to some other form
var otherForm = new MyForm();
Program.SwitchMainForm(otherForm);

0
private void buttonNextForm(object sender, EventArgs e)
{
    NextForm nf = new NextForm();//Object of the form that you want to open
    this.hide();//Hide cirrent form.
    nf.ShowModel();//Display the next form window
    this.Close();//While closing the NextForm, control will come again and will close this form as well
}

它不会工作。在显示下一个表单之前没有任何隐藏的感觉。它将同时执行,程序将终止。
Ahmet Karabulut

0
//if Form1 is old form and Form2 is the current form which we want to open, then
{
Form2 f2 = new Form1();

this.Hide();// To hide old form i.e Form1
f2.Show();
}


0
                     this.Visible = false;
                        //or                         // will make LOgin Form invisivble
                        //this.Enabled = false;
                         //  or
                       // this.Hide(); 



                        Form1 form1 = new Form1();
                        form1.ShowDialog();

                        this.Dispose();

1
这个答案又增加了这个讨论吗?这是重新声明,没有添加其他9个答案中的任何解释信息。
爱德华

0

我认为这容易得多:)

    private void btnLogin_Click(object sender, EventArgs e)
    {
        //this.Hide();
        //var mm = new MainMenu();
        //mm.FormClosed += (s, args) => this.Close();
        //mm.Show();

        this.Hide();
        MainMenu mm = new MainMenu();
        mm.Show();

    }

此解决方案不是此问题的相关答案。您的解决方案不会关闭当前表格,这意味着当前表格仍在处理中。
Ahmet Karabulut

-1

假设您有两个表单,第一个表单名称为Form1,第二个表单名称为Form2。您必须从Form1跳到Form2,然后在此处输入代码。编写如下代码:

在Form1上,我有一个名为Button1的按钮,并在其click选项上编写以下代码:

protected void Button1_Click(Object sender,EventArgs e)
{
    Form frm=new Form2();// I have created object of Form2
    frm.Show();
    this.Visible=false;
    this.Hide();
    this.Close();
    this.Dispose();
}

希望这段代码对您有帮助


这四种方法:this.Visible=false; this.Hide(); this.Close(); this.Dispose();是冗余的。您只需要Close()。关闭窗体会处理它,设置窗体的可见性与隐藏窗体相同,并且当窗体在下一个绘画事件之前不存在时,隐藏窗体毫无意义。
Servy

-3

我可以通过以下方法解决它:

private void button1_Click(object sender, EventArgs e)
{
    Form2 m = new Form2();
    m.Show();
    Form1 f = new Form1();
    this.Visible = false;
    this.Hide();
}

3
this.Visible = false然后this.Hide呢?为什么要做两次相同的事情?
Neolisk

8
另外,为什么要创建一个新的Form1东西却什么也不做呢?
Servy
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.