c # abrir um novo formulário e fechar o formulário atual?

89

Por exemplo, suponha que estou no formulário 1 e então quero:

  1. Abra o formulário 2 (a partir de um botão no formulário 1)
  2. Fechar formulário 1
  3. Foco no formulário 2
tnhan07
fonte
18
Usabilidade terrível. Se você estiver usando WinForms, basta criar uma janela de contêiner e substituir os painéis. Seus usuários vão adorar você por isso (e odiar você por não fazer isso)
Claus Jørgensen,
1
Ouça o Papai Noel! O que você está tentando alcançar é talvez a) Uma implementação de winforms de uma série de etapas sequenciais do tipo assistente ou b) Uma tentativa de mostrar um formulário de "resultado" após um formulário de "entrada / envio de dados". Independentemente de ser a) ou b), o comportamento da IU que você está tentando implementar é uma solução abaixo do ideal.
Simen S,
Cláusula de agradecimento e Simen S muito. Seus comentários são muito úteis para um iniciante como eu. Vou ler mais tutoriais sobre GUI e usabilidade. Você poderia me recomendar alguns úteis?
tnhan07,
Verifique também [respostas aqui] ( stackoverflow.com/questions/4759334/… ), se sua real intenção era apenas ter um formulário de login (ou algo semelhante).
ilias iliadis

Respostas:

194

A solução de Steve não funciona. Ao chamar this.Close (), o formulário atual é descartado junto com o form2. Portanto, você precisa ocultá-lo e definir o evento form2.Closed para chamar this.Close ().

private void OnButton1Click(object sender, EventArgs e)
{
    this.Hide();
    var form2 = new Form2();
    form2.Closed += (s, args) => this.Close(); 
    form2.Show();
}
Nihique
fonte
2
não há evento Closed nos formulários do windows em dot net. Você pode me dizer se é o evento FormClosed
Anjali
2
Esconder a primeira forma não a mantém na memória? Como podemos liberar esse recurso?
user2635088
5
form2.Closed += (s, args) => this.Close();Posso saber como funciona esta declaração? o que exatamente (s,args)é?
Yash Saraiya
1
(s, args) => this.Close();é uma expressão lambda. Ele cria uma função "no local" que é chamada quando o form2.Closedevento é disparado. (s, args)são apenas nomes para os parâmetros do lambda. Que para um manipulador de eventos geralmente são algo parecido (object sender, EventArgs e). Como a Closedassinatura do delegado do evento descreve seus tipos, os tipos não são fornecidos (Alguém, por favor, corrija minhas palavras, se necessário). // No geral, é apenas uma maneira complicada de não ter que declarar uma função inteira (manipulador de eventos) fora da função atual que manipula o Form2.Closedevento.
KDecker
1
está apenas escondendo a primeira forma e abrindo uma nova forma, mas não fechando a primeira
Uddyan Semwal
25

Tente fazer isso ...

{
    this.Hide();
    Form1 sistema = new Form1();
    sistema.ShowDialog();
    this.Close();
}
MontDeska
fonte
É o seguinte. Eu tenho um formulário principal. mas eu uso um pequeno formulário para um Login. Este formulário chama o formulário principal com este método. Ok, estamos bem aqui. O problema era quando o formulário principal mostra um formulário filho, e ao fechar o formulário filho ... fecha o formulário principal também. Então, já que estou usando o método publicado por Nihique. O código tem funcionado tão bem! ...
MontDeska
este código está funcionando para mim. Estou usando o VS 2015. Obrigado
IT Vlogs de
22

Muitas maneiras diferentes já foram descritas pelas outras respostas. No entanto, muitos deles estão envolvidos ShowDialog()ou form1permanecem abertos, mas ocultos. A melhor e mais intuitiva forma, em minha opinião, é simplesmente fechar form1e criar form2de um local externo (ou seja, não de dentro de nenhum desses formulários). No caso em que form1foi criado em Main, form2pode simplesmente ser criado usando Application.Runcomo form1antes. Aqui está um exemplo de cenário:

Preciso que o usuário insira suas credenciais para que eu possa autenticá-lo de alguma forma. Depois, se a autenticação for bem-sucedida, quero mostrar o aplicativo principal ao usuário. Para fazer isso, estou usando dois formulários: LogingForme MainForm. O LoginFormpossui um sinalizador que determina se a autenticação foi bem-sucedida ou não. Este sinalizador é então usado para decidir se deve criar a MainForminstância ou não. Nenhum desses formulários precisa saber sobre o outro e ambos os formulários podem ser abertos e fechados normalmente. Aqui está o código para isso:

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
fonte
Este é um bom truque do que esconder formulários. Quando temos formulários ocultos para sair do aplicativo, não basta fechar o formulário atual. Temos que usar Application.Exit (0) etc.
Peck_roideron
É bom, mas acho que é adequado para apenas 2 formulários. Que tal vários formulários alternando entre eles ??
Dr. MAF
Isso se restringe à execução de formulários em sequência, não em paralelo ou em cima uns dos outros, conforme solicitado pelo OP. Não sei por que isso seria restrito a apenas 2 formulários, no entanto. O código externo é livre para gerar quantas formas em sequência desejar. Alternar entre eles também pode ser feito pelo código externo. Ele pode verificar algum estado no formulário principal (como loginForm.UserSuccessfullyAuthenticatedantes) ou talvez o estado global para decidir se deve executar novamente o formulário de login, ou executar outro formulário, ou talvez encerrar o processo.
Manuzor
11

O problema começa com essa linha:

Application.Run(new Form1()); Que provavelmente pode ser encontrado em seu arquivo program.cs.

Esta linha indica que form1 deve tratar o loop de mensagens - em outras palavras, form1 é responsável por continuar executando sua aplicação - a aplicação será fechada quando form1 for fechado.

Existem várias maneiras de lidar com isso, mas todas elas de uma forma ou de outra não fecharão o form1.
(A menos que alteremos o tipo de projeto para algo diferente do aplicativo de formulários do Windows)

O que eu acho mais fácil para sua situação é criar 3 formulários:

  • form1 - permanecerá invisível e atuará como um gerente, você pode atribuí-lo para lidar com um ícone da bandeja se desejar.

  • form2 - terá o botão, que ao ser clicado fecha o form2 e abre o form3

  • form3 - terá a função do outro formulário que precisa ser aberto.

E aqui está um código de amostra para fazer isso:
(também adicionei um exemplo para fechar o aplicativo do terceiro formulário)

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: trabalhar com painéis ou carregar controles do usuário dinamicamente é mais acadêmico e preferível como padrões de produção da indústria - mas me parece que você está apenas tentando raciocinar sobre como as coisas funcionam - para esse propósito, este exemplo é melhor.

E agora que os princípios foram compreendidos, vamos tentar com apenas duas formas:

  • O primeiro formulário assumirá a função de gerente, assim como no exemplo anterior, mas também apresentará a primeira tela - portanto, não será fechada, apenas oculta.

  • O segundo formulário terá a função de mostrar a próxima tela e ao clicar em um botão fechará o aplicativo.


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

Se você alterar o exemplo anterior - exclua o form3 do projeto.

Boa sorte.

GY
fonte
6

Você não foi específico, mas parece que você estava tentando fazer o que eu faço nos meus aplicativos Win Forms: comece com um formulário de Login, depois de um login bem-sucedido, feche esse formulário e coloque o foco em um formulário Principal. É assim que eu faço:

  1. tornar frmMain o formulário de inicialização; é assim que meu Program.cs se parece:

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new frmMain());
    }
    
  2. em meu frmLogin, crie uma propriedade pública que seja inicializada como falsa e definida como verdadeira apenas se ocorrer um login bem-sucedido:

    public bool IsLoggedIn { get; set; }
    
  3. meu frmMain se parece com isto:

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

Sem sucesso de login? Saia do aplicativo. Caso contrário, continue com frmMain. Por ser o formulário de inicialização, quando fecha, o aplicativo termina.

Barry Novak
fonte
3

use este trecho de código em seu 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();
}

Eu peguei isso daqui

Lakshman
fonte
Observe que as respostas somente com link são desencorajadas, as respostas do SO devem ser o ponto final de uma busca por uma solução (em vez de outra parada de referências, que tendem a ficar obsoletas com o tempo). Considere adicionar uma sinopse independente aqui, mantendo o link como referência.
kleopatra de
2

Se você tiver dois formulários: frm_form1 e frm_form2. O código a seguir é usado para abrir frm_form2 e fechar frm_form1. (Para aplicativos de formulário do 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
fonte
1

Normalmente faço isso para alternar entre os formulários.

Em primeiro lugar, no arquivo de programa mantenho o ApplicationContext e adiciono um 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();
    }


}

Em seguida, em qualquer lugar no código agora chamo o método SwitchMainForm para alternar facilmente para o novo formulário.

// switch to some other form
var otherForm = new MyForm();
Program.SwitchMainForm(otherForm);
Namik Hajiyev
fonte
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
fonte
Não vai funcionar. Não faz sentido se esconder antes de mostrar o próximo formulário. Ele será executado em sametime e o programa será encerrado.
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();
}
user2186819
fonte
0

Este código pode ajudá-lo:

Master frm = new Master();

this.Hide();

frm.ShowDialog();

this.Close();
Jaydeo Kumar Dharpure
fonte
existe o aplicativo
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
fonte
1
O que esta resposta adiciona a esta discussão? Ele está reafirmando sem adicionar nenhuma informação explicativa presente nas outras 9 respostas.
Edward
0

Acho que é muito mais 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
fonte
Esta solução não é uma resposta relacionada a esta pergunta. Sua solução não fechará o formulário atual, isso significa que o formulário atual ainda está em processo.
Ahmet Karabulut
-1

Suponha que você tenha dois Formulários, o nome do primeiro formulário é Form1 e o segundo nome do formulário é Form2.You tem que pular do Form1 para o Form2 e inserir o código aqui. Escreva o código como o seguinte:

No Form1, tenho um botão chamado Button1 e, na opção de clique, escrevo o código abaixo:

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 ajude você

Shahnawaz
fonte
Esses quatro métodos: this.Visible=false; this.Hide(); this.Close(); this.Dispose();são redundantes. Você não precisa de nada mais do que Close(). Fechar um formulário descarta-o, definir a visibilidade do formulário é o mesmo que ocultá-lo, e ocultar um formulário é inútil quando ele não existirá antes do próximo evento de pintura.
Servy
-3

Eu iria resolver isso fazendo:

private void button1_Click(object sender, EventArgs e)
{
    Form2 m = new Form2();
    m.Show();
    Form1 f = new Form1();
    this.Visible = false;
    this.Hide();
}
Polash
fonte
3
this.Visible = falsee então this.Hide? Por que fazer a mesma coisa duas vezes?
Neolisk
8
Além disso, por que você está criando um novo Form1e não fazendo nada com ele?
Servy