c # otworzyć nowy formularz, a następnie zamknąć bieżący formularz?

89

Na przykład załóżmy, że jestem w formie 1, a następnie chcę:

  1. Otwórz formularz 2 (z przycisku w formularzu 1)
  2. Zamknij formularz 1
  3. Skoncentruj się na formularzu 2
tnhan07
źródło
18
Straszna użyteczność. Jeśli używasz WinForms, po prostu utwórz okno kontenera i zamiast tego zamień panele. Użytkownicy będą cię za to kochać (i nienawidzę cię za nie robi)
Claus Jørgensen
1
Posłuchaj Mikołaja! To, co próbujesz osiągnąć, to być może a) implementacja programu WinForm przypominająca kreatora, sekwencyjna seria kroków lub b) próba wyświetlenia formularza „wynikowego” po formularzu „wprowadzenie / przesłanie danych”. Niezależnie od tego, czy jest to a) czy b) zachowanie interfejsu użytkownika, które próbujesz zaimplementować, jest rozwiązaniem nieoptymalnym.
Simen S
Dziękuję Clause i Simen S. Twoje komentarze są bardzo pomocne dla początkujących, takich jak ja. Przeczytam więcej tutoriali na temat GUI i użyteczności. Czy mógłbyś polecić mi kilka przydatnych?
tnhan07
Sprawdź również [odpowiedzi tutaj] ( stackoverflow.com/questions/4759334/… ), czy Twoim prawdziwym zamiarem było posiadanie formularza logowania (lub podobnego).
ilias iliadis

Odpowiedzi:

193

Rozwiązanie Steve'a nie działa. Podczas wywoływania this.Close (), bieżący formularz jest usuwany razem z form2. Dlatego musisz to ukryć i ustawić zdarzenie form2.Closed, aby wywoł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
źródło
2
nie ma zdarzenia Closed w formularzach windows w dot net. Czy możesz mi powiedzieć, czy to wydarzenie FormClosed
Anjali
2
Czy ukrycie pierwszej formy nie zachowuje jej w pamięci? Jak możemy uwolnić ten zasób?
user2635088
5
form2.Closed += (s, args) => this.Close();Czy mogę wiedzieć, jak działa to stwierdzenie? co to właściwie (s,args)jest?
Yash Saraiya
1
(s, args) => this.Close();jest wyrażeniem lambda. Tworzy funkcję „na miejscu”, która jest wywoływana, gdy form2.Closedzdarzenie jest uruchamiane. (s, args)to tylko nazwy parametrów lambdy. Które dla obsługi zdarzeń są zwykle czymś w rodzaju (object sender, EventArgs e). Ponieważ Closedpodpis delegata wydarzenia opisuje ich typy, typy nie są podawane (ktoś w razie potrzeby skoryguje moje sformułowanie). // Ogólnie rzecz biorąc, jest to po prostu trudny sposób, aby nie musieć deklarować całej funkcji (obsługi zdarzenia) poza bieżącą, która obsługuje Form2.Closedzdarzenie.
KDecker,
1
po prostu ukrywa pierwszą formę i otwiera nową, ale nie zamyka pierwszej
Uddyan Semwal
25

Spróbuj to zrobić ...

{
    this.Hide();
    Form1 sistema = new Form1();
    sistema.ShowDialog();
    this.Close();
}
MontDeska
źródło
Oto rzecz. Mam formularz główny. ale używam małego formularza do logowania. Ten formularz wywołuje formularz główny za pomocą tej metody. Ok, jesteśmy tutaj dobrzy. Problem polegał na tym, że formularz główny wyświetla formularz podrzędny, a podczas zamykania formularza podrzędnego ... zamyka również formularz główny. Więc ponieważ używam metody opublikowanej przez Nihique. Kod działa tak dobrze! ...
MontDeska
ten kod działa dla mnie. Używam VS 2015. Dzięki
IT Vlogi
21

W innych odpowiedziach opisano już wiele różnych sposobów. Jednak wielu z nich jest zaangażowanych ShowDialog()lub form1pozostaje otwartych, ale ukrytych. Moim zdaniem najlepszym i najbardziej intuicyjnym sposobem jest po prostu zamknięcie, form1a następnie tworzenie form2z zewnętrznego miejsca (tj. Nie z poziomu żadnej z tych form). W przypadku, gdy form1został utworzony w Main, form2można go po prostu utworzyć za pomocą Application.Runtak jak form1wcześniej. Oto przykładowy scenariusz:

Chcę, aby użytkownik wprowadził swoje dane uwierzytelniające, abym mógł je w jakiś sposób uwierzytelnić. Następnie, jeśli uwierzytelnienie się powiedzie, chcę pokazać użytkownikowi główną aplikację. Aby to osiągnąć, używam dwóch formularzy: LogingFormi MainForm. LoginFormMa flagę, która określa, czy autoryzacja przebiegła pomyślnie, czy nie. Ta flaga jest następnie używana do podjęcia decyzji, czy utworzyć MainForminstancję, czy nie. Żaden z tych formularzy nie musi wiedzieć o drugim i oba formularze można z wdziękiem otwierać i zamykać. Oto kod:

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
źródło
To fajna sztuczka niż ukrywanie form. Gdy mamy ukryte formularze do wyjścia z aplikacji, nie wystarczy zamknąć aktualny formularz. Musimy użyć Application.Exit (0) itd.
Peck_conyon
To fajne, ale myślę, że nadaje się tylko do 2 form. A co z wieloma formularzami przełączającymi się między nimi?
Dr MAF,
Ogranicza się to do uruchamiania formularzy w kolejności, a nie równolegle lub jeden na drugim, jak żądał PO. Nie jestem jednak pewien, dlaczego miałoby to być ograniczone tylko do 2 formularzy. Kod zewnętrzny może tworzyć dowolną liczbę formularzy w kolejności, w jakiej chcesz. Przełączanie się między nimi można również wykonać za pomocą kodu zewnętrznego. Mógłby sprawdzić stan w głównym formularzu (jak loginForm.UserSuccessfullyAuthenticatedpoprzednio) lub stan globalny, aby zdecydować, czy ponownie uruchomić formularz logowania, uruchomić inny formularz, a może zakończyć proces.
Manuzor
11

Problem tkwi w tej linii:

Application.Run(new Form1()); Który prawdopodobnie można znaleźć w pliku program.cs.

Ta linia wskazuje, że form1 ma obsługiwać pętlę komunikatów - innymi słowy form1 jest odpowiedzialny za kontynuowanie wykonywania aplikacji - aplikacja zostanie zamknięta po zamknięciu formularza form1.

Jest kilka sposobów, aby sobie z tym poradzić, ale wszystkie z nich w taki czy inny sposób nie zamkną formularza1.
(Chyba że zmienimy typ projektu na inny niż aplikacja Windows Forms)

Myślę, że najłatwiej w twojej sytuacji jest utworzenie 3 formularzy:

  • form1 - pozostanie niewidoczny i będzie działał jako menedżer, możesz go przypisać do obsługi ikony w zasobniku, jeśli chcesz.

  • form2 - będzie miał przycisk, którego kliknięcie zamknie formularz2 i otworzy formularz3

  • form3 - będzie pełnił rolę drugiego formularza, który trzeba otworzyć.

A oto przykładowy kod, aby to osiągnąć:
(dodałem również przykład zamykania aplikacji z 3. formularza)

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


Uwaga: praca z panelami lub dynamiczne ładowanie elementów sterujących użytkownika jest bardziej akademickie i preferowane jako branżowe standardy produkcji - ale wydaje mi się, że po prostu próbujesz zrozumieć, jak to działa - w tym celu ten przykład jest lepszy.

A teraz, gdy zasady są już zrozumiane, wypróbujmy to tylko w dwóch formach:

  • Pierwsza forma przyjmie rolę menedżera, tak jak w poprzednim przykładzie, ale będzie również przedstawiać pierwszy ekran - więc nie zostanie zamknięty tylko ukryty.

  • Drugi formularz przejmie rolę pokazania kolejnego ekranu i po kliknięciu przycisku zamknie aplikację.


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

Jeśli zmienisz poprzedni przykład - usuń formularz3 z projektu.

Powodzenia.

GY
źródło
6

Nie byłeś konkretny, ale wygląda na to, że próbowałeś zrobić to, co robię w moich aplikacjach Win Forms: zacznij od formularza logowania, a następnie po pomyślnym zalogowaniu zamknij ten formularz i skup się na formularzu głównym. Oto jak to robię:

  1. zrobić frmMain formularz startowy; tak wygląda mój Program.cs:

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new frmMain());
    }
    
  2. w moim frmLogin utwórz właściwość publiczną, która zostanie zainicjowana na false i ustawiona na true tylko wtedy, gdy nastąpi pomyślne logowanie:

    public bool IsLoggedIn { get; set; }
    
  3. mój frmMain wygląda następująco:

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

Brak pomyślnego logowania? Zamknij aplikację. W przeciwnym razie kontynuuj z frmMain. Ponieważ jest to formularz startowy, po zamknięciu aplikacja kończy się.

Barry Novak
źródło
3

użyj tego fragmentu kodu w swoim formularzu 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();
}

Mam to stąd

lakshman
źródło
Należy pamiętać, że odradza się udzielanie odpowiedzi zawierających tylko łącze, a odpowiedzi SO powinny być końcowym punktem poszukiwania rozwiązania (w porównaniu z kolejną przerwą w dostępie do odniesień, które z czasem stają się nieaktualne). Rozważ dodanie tutaj samodzielnego streszczenia, zachowując link jako odniesienie.
kleopatra
2

Jeśli masz dwa formularze: frm_form1 i frm_form2. Poniższy kod służy do otwierania frm_form2 i zamykania frm_form1. (Dla aplikacji formularzy systemu 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();
grzywa
źródło
1

Zwykle robię to, aby przełączać się między formularzami.

Najpierw w pliku programu zachowuję ApplicationContext i dodaję metodę pomocniczą 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();
    }


}

Następnie w dowolnym miejscu kodu wywołuję teraz metodę SwitchMainForm , aby łatwo przejść do nowego formularza.

// switch to some other form
var otherForm = new MyForm();
Program.SwitchMainForm(otherForm);
Namik Hajiyev
źródło
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
źródło
To nie zadziała. Nie ma sensu ukrywać się przed wyświetleniem kolejnego formularza. Uruchomi się o tej samej porze i program zostanie zakończony.
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
źródło
0

Ten kod może ci pomóc:

Master frm = new Master();

this.Hide();

frm.ShowDialog();

this.Close();
Jaydeo Kumar Dharpure
źródło
to istnieje aplikacja
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
źródło
1
Co z tą odpowiedzią dodaje do tej dyskusji? Jest to powtórzenie bez dodawania jakichkolwiek informacji wyjaśniających obecnych w 9 innych odpowiedziach.
Edward,
0

Myślę, że to jest dużo łatwiejsze :)

    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
źródło
To rozwiązanie nie jest odpowiedzią na to pytanie. Twoje rozwiązanie nie zamknie obecnego formularza, co oznacza, że ​​obecna forma jest nadal w toku.
Ahmet Karabulut
-1

Załóżmy, że masz dwa formularze, pierwsza nazwa formularza to Form1, a druga nazwa formularza to Form2. Musisz przejść z Form1 do Form2 i wprowadzić kod tutaj. Napisz kod jak poniżej:

Na Form1 mam jeden przycisk o nazwie Button1 i po jego kliknięciu napisz poniższy kod:

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

Mam nadzieję, że ten kod ci pomoże

Shahnawaz
źródło
Te cztery metody: this.Visible=false; this.Hide(); this.Close(); this.Dispose();są zbędne. Nie potrzebujesz niczego więcej niż Close(). Zamknięcie formularza usuwa go, ustawienie widoczności formularza jest tym samym, co ukrycie go, a ukrycie formularza jest bezcelowe, gdy nie będzie istnieć przed kolejnym zdarzeniem malowania.
Servy
-3

Rozwiązałbym to, wykonując:

private void button1_Click(object sender, EventArgs e)
{
    Form2 m = new Form2();
    m.Show();
    Form1 f = new Form1();
    this.Visible = false;
    this.Hide();
}
Polash
źródło
3
this.Visible = falsea potem this.Hide? Dlaczego robisz to samo dwa razy?
Neolisk
8
Poza tym, dlaczego tworzysz nowe Form1i nic z tym nie robisz?
Servy