c # abrir un nuevo formulario y luego cerrar el formulario actual?

89

Por ejemplo, suponga que estoy en el formulario 1, entonces quiero:

  1. Abrir formulario 2 (desde un botón en el formulario 1)
  2. Cerrar formulario 1
  3. Centrarse en la forma 2
tnhan07
fuente
18
Terrible usabilidad. Si está utilizando WinForms, simplemente cree una ventana contenedora y reemplace los paneles. Sus usuarios lo amarán por eso (y lo odiarán por no hacerlo)
Claus Jørgensen
1
¡Escucha a Claus! Lo que está tratando de lograr es quizás a) Una implementación winforms de una serie secuencial de pasos similar a un asistente o b) Un intento de mostrar un formulario de "resultado" después de un formulario de "entrada / envío de datos". Independientemente de si es a) ob), el comportamiento de la interfaz de usuario que está intentando implementar es una solución subóptima.
Simen S
Muchas gracias Clause y Simen S. Tus comentarios son muy útiles para un principiante como yo. Leeré más tutoriales sobre GUI y usabilidad. ¿Podrías recomendarme algunos útiles?
tnhan07
Consulte también [las respuestas aquí] ( stackoverflow.com/questions/4759334/… ), si su intención real era solo tener un formulario de inicio de sesión (o similar).
ilias iliadis

Respuestas:

193

La solución de Steve no funciona. Al llamar a this.Close (), la forma actual se elimina junto con form2. Por lo tanto, debe ocultarlo y configurar el evento form2.Closed para llamar a this.Close ().

private void OnButton1Click(object sender, EventArgs e)
{
    this.Hide();
    var form2 = new Form2();
    form2.Closed += (s, args) => this.Close(); 
    form2.Show();
}
nihique
fuente
2
no hay ningún evento cerrado en formularios de Windows en dot net. ¿Puedes decirme si es el evento FormClosed
Anjali
2
¿Ocultar la primera forma no la conserva todavía en la memoria? ¿Cómo podemos liberar ese recurso?
user2635088
5
form2.Closed += (s, args) => this.Close();¿Puedo saber cómo funciona esta declaración? que (s,args)es exactamente
Yash Saraiya
1
(s, args) => this.Close();es una expresión lambda. Crea una función "en el lugar" que se llama cuando form2.Closedse dispara el evento. (s, args)son solo nombres para los parámetros de la lambda. Que para un controlador de eventos suelen ser algo así como (object sender, EventArgs e). Debido a que la Closedfirma del delegado del evento describe sus tipos, no se dan los tipos (alguien corrija mi redacción si es necesario). // En general, es solo una forma complicada de no tener que declarar una función completa (controlador de eventos) fuera de la actual que maneja el Form2.Closedevento.
KDecker
1
es solo ocultar la primera forma y abrir una nueva forma pero no cerrar la primera forma
Uddyan Semwal
25

Intenta hacer esto ...

{
    this.Hide();
    Form1 sistema = new Form1();
    sistema.ShowDialog();
    this.Close();
}
MontDeska
fuente
Aquí está la cosa. Tengo un formulario principal. pero utilizo un pequeño formulario para iniciar sesión. Este formulario llama al formulario principal con este método. Ok, estamos bien aquí. El problema fue cuando el formulario principal muestra un formulario secundario y al cerrar el formulario secundario ... también cierra el formulario principal. Entonces, ya que estoy usando el método publicado por Nihique. ¡El código ha estado funcionando muy bien! ...
MontDeska
este código me funciona. estoy usando VS 2015. Gracias
IT Vlogs
21

Las otras respuestas ya han descrito muchas formas diferentes. Sin embargo, muchos de ellos están involucrados ShowDialog()o form1permanecen abiertos pero ocultos. La mejor y más intuitiva forma en mi opinión es simplemente cerrar form1y luego crear form2desde una ubicación externa (es decir, no desde dentro de ninguna de esas formas). En el caso de que form1se creó en Main, form2simplemente se puede crear usando Application.Runcomo form1antes. Aquí hay un escenario de ejemplo:

Necesito que el usuario ingrese sus credenciales para poder autenticarlos de alguna manera. Luego, si la autenticación fue exitosa, quiero mostrar la aplicación principal al usuario. Para lograr esto, estoy usando dos formas: LogingFormy MainForm. El LoginFormtiene una bandera que determina si la autenticación se ha realizado correctamente o no. Luego, esta bandera se usa para decidir si crear la MainForminstancia o no. Ninguno de estos formularios necesita conocer el otro y ambos formularios se pueden abrir y cerrar con elegancia. Aquí está el código para esto:

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());
        }
    }
}
Manuzor
fuente
Este es un buen truco que esconder formas. Cuando tenemos formularios ocultos para salir de la aplicación no basta con cerrar el formulario actual. Tenemos que usar Application.Exit (0), etc.
Peck_conyon
Es bueno, pero creo que solo es adecuado para 2 formas. ¿Qué pasa con las múltiples formas que cambian entre ellas?
Dr. MAF
Esto se limita a ejecutar formularios en secuencia, no en paralelo o uno encima del otro, como pidió el OP. Sin embargo, no estoy seguro de por qué esto estaría restringido a solo 2 formularios. El código externo es libre de generar tantas formas en secuencia como desee. El código externo también puede alternar entre ellos. Podría verificar algún estado en el formulario principal (como loginForm.UserSuccessfullyAuthenticatedantes) o tal vez el estado global para decidir si volver a ejecutar el formulario de inicio de sesión, ejecutar otro formulario o tal vez terminar el proceso.
Manuzor
11

El problema comienza con esa línea:

Application.Run(new Form1()); Que probablemente se puede encontrar en su archivo program.cs.

Esta línea indica que form1 debe manejar el ciclo de mensajes; en otras palabras, form1 es responsable de seguir ejecutando su aplicación; la aplicación se cerrará cuando form1 se cierre.

Hay varias formas de manejar esto, pero todas ellas de una forma u otra no cerrarán form1.
(A menos que cambiemos el tipo de proyecto a algo que no sea la aplicación de formularios de Windows)

El que creo que es más fácil para tu situación es crear 3 formularios:

  • form1: permanecerá invisible y actuará como administrador, puede asignarlo para manejar un icono de bandeja si lo desea.

  • form2: tendrá el botón, que al hacer clic en él, cerrará form2 y abrirá form3

  • form3: tendrá el papel del otro formulario que debe abrirse.

Y aquí hay un código de muestra para lograr eso:
(también agregué un ejemplo para cerrar la aplicación desde el tercer formulario)

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.
    }
}


Nota: trabajar con paneles o cargar controles de usuario dinámicamente es más académico y preferible como estándares de producción de la industria, pero me parece que solo está tratando de razonar sobre cómo funcionan las cosas, para ese propósito, este ejemplo es mejor.

Y ahora que se entienden los principios, intentémoslo con solo dos formas:

  • El primer formulario asumirá el rol de administrador al igual que en el ejemplo anterior, pero también presentará la primera pantalla, por lo que no se cerrará, solo se ocultará.

  • El segundo formulario asumirá la función de mostrar la siguiente pantalla y al hacer clic en un botón se cerrará la aplicación.


    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();
        }
    }

Si modifica el ejemplo anterior, elimine form3 del proyecto.

Buena suerte.

GY
fuente
6

No fue específico, pero parece que estaba tratando de hacer lo que yo hago en mis aplicaciones Win Forms: comience con un formulario de inicio de sesión, luego, después de iniciar sesión correctamente, cierre ese formulario y enfóquese en un formulario principal. Así es como lo hago:

  1. haga frmMain el formulario de inicio; así es como se ve mi Program.cs:

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new frmMain());
    }
    
  2. en mi frmLogin, cree una propiedad pública que se inicialice en falso y se establezca en verdadero solo si se produce un inicio de sesión exitoso:

    public bool IsLoggedIn { get; set; }
    
  3. mi frmMain se ve así:

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

¿No ha iniciado sesión correctamente? Salga de la aplicación. De lo contrario, continúe con frmMain. Como es el formulario de inicio, cuando se cierra, la aplicación finaliza.

Barry Novak
fuente
3

use este fragmento de código en su formulario1.

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();
}

Tengo esto de aqui

lakshman
fuente
Tenga en cuenta que se desaconsejan las respuestas de solo enlace, las respuestas SO deben ser el punto final de la búsqueda de una solución (frente a otra escala de referencias, que tienden a volverse obsoletas con el tiempo). Considere agregar una sinopsis independiente aquí, manteniendo el enlace como referencia.
kleopatra
2

Si tiene dos formularios: frm_form1 y frm_form2, el siguiente código se utiliza para abrir frm_form2 y cerrar frm_form1. (Para la aplicación de formulario de 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();
maneesh
fuente
1

Normalmente hago esto para alternar entre formularios.

En primer lugar, en el archivo de programa guardo ApplicationContext y agrego un método auxiliar 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();
    }


}

Luego, en cualquier parte del código ahora llamo al método SwitchMainForm para cambiar fácilmente al nuevo formulario.

// switch to some other form
var otherForm = new MyForm();
Program.SwitchMainForm(otherForm);
Namik Hajiyev
fuente
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
}
Prateek Shukla
fuente
No funcionará. No tiene sentido esconderse antes de mostrar el siguiente formulario. Se ejecutará a la misma hora y el programa se terminará.
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();
}
usuario2186819
fuente
0

Este código puede ayudarlo a:

Master frm = new Master();

this.Hide();

frm.ShowDialog();

this.Close();
Jaydeo Kumar Dharpure
fuente
esta existe la aplicación
Baqer Naqvi
0
                     this.Visible = false;
                        //or                         // will make LOgin Form invisivble
                        //this.Enabled = false;
                         //  or
                       // this.Hide(); 



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

                        this.Dispose();
Aamir Zargar
fuente
1
¿Qué hay de esta respuesta que se suma a esta discusión? Se repite sin agregar ninguna información de explicación presente en las otras 9 respuestas.
Edward
0

Creo que esto es mucho más fácil :)

    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();

    }
Sachith
fuente
Esta solución no es una respuesta relacionada para esta pregunta. Su solución no cerrará el formulario actual, esto significa que el formulario actual aún está en proceso.
Ahmet Karabulut
-1

Suponga que tiene dos formularios, el nombre del primer formulario es Form1 y el nombre del segundo formulario es Form2. Debe saltar de Form1 a Form2, ingrese el código aquí. Escriba código como el siguiente:

En Form1 tengo un botón llamado Button1, y en su opción de clic, escriba el siguiente código:

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();
}

Espero que este código te ayude

Shahnawaz
fuente
Estos cuatro métodos: this.Visible=false; this.Hide(); this.Close(); this.Dispose();son redundantes. No necesitas nada más que Close(). Cerrar un formulario lo elimina, establecer la visibilidad del formulario es lo mismo que ocultarlo, y ocultar un formulario no tiene sentido cuando no va a existir antes de su próximo evento de pintura.
Servicio
-3

Lo resolvería haciendo:

private void button1_Click(object sender, EventArgs e)
{
    Form2 m = new Form2();
    m.Show();
    Form1 f = new Form1();
    this.Visible = false;
    this.Hide();
}
Polash
fuente
3
this.Visible = falsey luego this.Hide? ¿Por qué hacer lo mismo dos veces?
Neolisk
8
Además, ¿por qué estás creando una nueva Form1y no haces nada con ella?
Servicio