c # aprire un nuovo modulo quindi chiudere il modulo corrente?


89

Ad esempio, supponiamo che io sia nel modulo 1, quindi voglio:

  1. Apri modulo 2 (da un pulsante nel modulo 1)
  2. Chiudi modulo 1
  3. Concentrati sul modulo 2

18
Terribile usabilità. Se stai usando WinForms, crea semplicemente una finestra contenitore e sostituisci invece i pannelli. I tuoi utenti ti adoreranno per questo (e ti odieranno per non farlo)
Claus Jørgensen

1
Ascolta Claus! Quello che stai cercando di ottenere è forse a) un'implementazione winform di una serie sequenziale di passaggi simile a una procedura guidata oppure b) Un tentativo di mostrare un modulo "risultato" dopo un modulo "immissione / invio dati". Indipendentemente dal fatto che si tratti di a) o b), il comportamento dell'interfaccia utente che si sta tentando di implementare è una soluzione non ottimale.
Simen S

Grazie Clause e Simen S molto. I tuoi commenti sono molto utili per un principiante come me. Leggerò altri tutorial su GUI e usabilità. Potresti consigliarmi alcuni utili?
tnhan07


Controlla anche [risponde qui] ( stackoverflow.com/questions/4759334/… ), se la tua vera intenzione era solo quella di avere un modulo di accesso (o simile).
ilias iliadis

Risposte:


194

La soluzione di Steve non funziona. Quando si chiama this.Close (), il form corrente viene eliminato insieme a form2. Pertanto è necessario nasconderlo e impostare l'evento form2.Closed per chiamare this.Close ().

private void OnButton1Click(object sender, EventArgs e)
{
    this.Hide();
    var form2 = new Form2();
    form2.Closed += (s, args) => this.Close(); 
    form2.Show();
}

2
non vi è alcun evento chiuso in windows form in dot net. Puoi dirmi che è l'evento FormClosed
Anjali

2
Nascondere la prima forma non la mantiene ancora memoria? Come possiamo rilasciare quella risorsa?
user2635088

5
form2.Closed += (s, args) => this.Close();Posso sapere come funziona questa affermazione? che cos'è esattamente (s,args)?
Yash Saraiya

1
(s, args) => this.Close();è un'espressione lambda. Crea una funzione "sul posto" che viene chiamata quando form2.Closedviene generato l' evento. (s, args)sono solo nomi per i parametri di lambda. Che per un gestore di eventi di solito sono qualcosa di simile (object sender, EventArgs e). Poiché la Closedfirma del delegato dell'evento descrive i loro tipi, i tipi non vengono forniti (qualcuno corregga la mia formulazione se necessario). // Nel complesso è solo un modo complicato per non dover dichiarare un'intera funzione (gestore di eventi) al di fuori di quella corrente che gestisce l' Form2.Closedevento.
KDecker

1
sta solo nascondendo il primo modulo e aprendo un nuovo modulo ma non chiudendo il primo modulo
Uddyan Semwal

25

Prova a farlo ...

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

Ecco la cosa. Ho un modulo principale. ma io uso un piccolo modulo per un login. Questo modulo chiama il modulo principale con questo metodo. Ok, qui stiamo bene. Il problema era quando il modulo principale mostra un modulo figlio e alla chiusura del modulo figlio ... chiude anche il modulo principale. Quindi, poiché sto usando il metodo pubblicato da Nihique. Il codice ha funzionato così bene! ...
MontDeska

questo codice funziona per me. sto usando VS 2015. Grazie
IT Vlogs

22

Molti modi diversi sono già stati descritti dalle altre risposte. Tuttavia, molti di loro sono coinvolti ShowDialog()o form1rimangono aperti ma nascosti. Il modo migliore e più intuitivo secondo me è semplicemente chiudere form1e quindi creare form2da una posizione esterna (cioè non dall'interno di nessuna di queste forme). Nel caso in cui è form1stato creato in Main, form2può essere semplicemente creato utilizzando Application.Runproprio comeform1 prima. Ecco uno scenario di esempio:

Ho bisogno che l'utente inserisca le proprie credenziali per poterle autenticare in qualche modo. Successivamente, se l'autenticazione ha avuto successo, voglio mostrare l'applicazione principale all'utente. Per fare ciò, sto usando due forme: LogingForme MainForm. L' LoginFormha una bandiera che determina se l'autenticazione ha avuto successo o meno. Questo flag viene quindi utilizzato per decidere se creare MainFormo meno l' istanza. Nessuno di questi moduli deve conoscere l'altro ed entrambi i moduli possono essere aperti e chiusi con grazia. Ecco il codice per questo:

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

Questo è un bel trucco che nascondere le forme. Quando abbiamo moduli nascosti per uscire dall'applicazione, non è sufficiente chiudere il modulo corrente. Dobbiamo usare Application.Exit (0) ecc.
Peck_conyon

È carino, ma penso che sia adatto solo per 2 forme. Che ne dici di più moduli che cambiano tra loro?
Dr. MAF

Ciò è limitato all'esecuzione di moduli in sequenza, non in parallelo o uno sopra l'altro, come richiesto dall'OP. Non sono sicuro del motivo per cui questo dovrebbe essere limitato a solo 2 forme, però. Il codice esterno è libero di generare tutte le forme in sequenza desiderate. La commutazione tra di loro può essere eseguita anche dal codice esterno. Potrebbe controllare uno stato nel modulo principale (come loginForm.UserSuccessfullyAuthenticatedprima) o forse uno stato globale per decidere se eseguire nuovamente il modulo di accesso o eseguire un altro modulo o forse terminare il processo.
Manuzor,

11

Il problema inizia con quella linea:

Application.Run(new Form1()); Che probabilmente si trova nel file program.cs.

Questa riga indica che form1 deve gestire il ciclo dei messaggi - in altre parole form1 è responsabile di continuare a eseguire l'applicazione - l'applicazione verrà chiusa quando form1 viene chiuso.

Ci sono diversi modi per gestire questo problema, ma tutti in un modo o nell'altro non chiuderanno form1.
(A meno che non cambiamo il tipo di progetto in qualcosa di diverso dall'applicazione Windows Form)

Quello che penso sia più facile per la tua situazione è creare 3 moduli:

  • form1 - rimarrà invisibile e agirà come un manager, puoi assegnarlo a gestire un'icona nel vassoio se lo desideri.

  • form2 - avrà il pulsante, che se cliccato chiuderà form2 e aprirà form3

  • form3 - avrà il ruolo dell'altro modulo che deve essere aperto.

Ed ecco un codice di esempio per farlo:
(Ho anche aggiunto un esempio per chiudere l'app dal 3 ° modulo)

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: lavorare con i pannelli o caricare dinamicamente i controlli utente è più accademico e preferibile come standard di produzione del settore - ma mi sembra che tu stia solo cercando di ragionare su come funzionano le cose - a tal fine questo esempio è migliore.

E ora che i principi sono compresi proviamolo con due sole forme:

  • Il primo modulo assumerà il ruolo di manager proprio come nell'esempio precedente ma presenterà anche la prima schermata, quindi non verrà chiuso ma solo nascosto.

  • Il secondo modulo avrà il ruolo di mostrare la schermata successiva e facendo clic su un pulsante si chiuderà l'applicazione.


    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 modifichi l'esempio precedente, elimina form3 dal progetto.

In bocca al lupo.


6

Non eri specifico, ma sembra che tu stia cercando di fare quello che faccio io nelle mie app Win Forms: inizia con un modulo di accesso, quindi dopo aver effettuato correttamente l'accesso, chiudi quel modulo e concentrati su un modulo principale. Ecco come lo faccio:

  1. rendere frmMain il form di avvio; questo è l'aspetto del mio Program.cs:

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new frmMain());
    }
    
  2. nel mio frmLogin, crea una proprietà pubblica che viene inizializzata su false e impostata su true solo se si verifica un accesso riuscito:

    public bool IsLoggedIn { get; set; }
    
  3. my frmMain ha questo aspetto:

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

Nessun accesso riuscito? Esci dall'applicazione. Altrimenti, continuare con frmMain. Poiché è il modulo di avvio, quando si chiude, l'applicazione termina.


3

usa questo snippet di codice nel tuo modulo 1.

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

L'ho preso da qui


Si noti che le risposte di solo collegamento sono scoraggiate, quindi le risposte dovrebbero essere il punto finale di una ricerca di una soluzione (rispetto a un'altra sosta di riferimenti, che tendono a diventare obsoleti nel tempo). Si prega di considerare l'aggiunta di una sinossi indipendente qui, mantenendo il collegamento come riferimento.
kleopatra

2

Se hai due moduli: frm_form1 e frm_form2. Il codice seguente viene utilizzato per aprire frm_form2 e chiudere frm_form1. (Per l'applicazione Windows Form)

        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

Di solito lo faccio per passare da una forma all'altra.

In primo luogo, nel file di programma mantengo ApplicationContext e aggiungo un metodo SwitchMainForm di supporto .

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


}

Quindi in qualsiasi punto del codice ora chiamo il metodo SwitchMainForm per passare facilmente al nuovo modulo.

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

Non funzionerà. Non ha senso nascondersi prima di mostrare il modulo successivo. Verrà eseguito allo stesso tempo e il programma verrà terminato.
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
Che cosa circa questa risposta aggiunge a questa discussione? Sta riaffermando senza aggiungere alcuna informazione di spiegazione presente nelle altre 9 risposte.
Edward,

0

Penso che sia molto più facile :)

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

    }

Questa soluzione non è una risposta correlata a questa domanda. La tua soluzione non chiuderà il modulo attuale, questo significa che il modulo attuale è ancora in corso.
Ahmet Karabulut

-1

Supponiamo di avere due form, il nome del primo modulo è Form1 e il nome del secondo modulo è Form2. Devi passare da Form1 a Form2 inserisci il codice qui Scrivi il codice come segue:

Su Form1 ho un pulsante chiamato Button1 e sulla sua opzione di clic scrivi sotto il codice:

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

Spero che questo codice ti aiuti


Questi quattro metodi: this.Visible=false; this.Hide(); this.Close(); this.Dispose();sono ridondanti. Non hai bisogno di nient'altro che Close(). La chiusura di un modulo lo elimina, impostare la visibilità del modulo equivale a nasconderlo e nascondere un modulo è inutile quando non esisterà prima del prossimo evento di disegno.
Servizio

-3

Lo risolverei facendo:

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 = falsee poi this.Hide? Perché fare la stessa cosa due volte?
Neolisk

8
Inoltre, perché ne crei uno nuovo Form1e non ne fai nulla?
Servizio
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.