c # เปิดแบบฟอร์มใหม่จากนั้นปิดแบบฟอร์มปัจจุบัน?


89

ตัวอย่างเช่นสมมติว่าฉันอยู่ในรูปแบบที่ 1 แล้วฉันต้องการ:

  1. เปิดฟอร์ม 2 (จากปุ่มในรูปแบบ 1)
  2. ปิดแบบฟอร์ม 1
  3. เน้นรูปแบบ 2

18
การใช้งานแย่มาก หากคุณใช้ WinForms ให้สร้างหน้าต่างคอนเทนเนอร์แล้วเปลี่ยนพาเนลแทน ผู้ใช้ของคุณจะรักคุณ (และเกลียดคุณที่ไม่ได้ทำ)
Claus Jørgensen

1
ฟัง Claus! สิ่งที่คุณพยายามจะบรรลุอาจเป็น a) การใช้งานแบบ winforms ของชุดขั้นตอนตามลำดับที่เหมือนวิซาร์ดหรือ b) ความพยายามที่จะแสดงรูปแบบ "ผลลัพธ์" หลังจากแบบฟอร์ม "การป้อนข้อมูล / ส่ง" ไม่ว่าจะเป็น a) หรือ b) ลักษณะการทำงานของ UI ที่คุณพยายามนำไปใช้นั้นเป็นโซลูชันที่ไม่เหมาะสม
Simen S

ขอบคุณ Clause และ Simen S มาก ความคิดเห็นของคุณมีประโยชน์มากสำหรับมือใหม่อย่างฉัน ฉันจะอ่านบทแนะนำเพิ่มเติมเกี่ยวกับ GUI และการใช้งาน คุณช่วยแนะนำสิ่งที่มีประโยชน์ให้ฉันได้ไหม
tnhan07


ตรวจสอบ [คำตอบที่นี่] ( stackoverflow.com/questions/4759334/… ) หากความตั้งใจจริงของคุณเพียงแค่มีแบบฟอร์มเข้าสู่ระบบ (หรือเหมือนกัน)
ilias iliadis

คำตอบ:


194

วิธีแก้ปัญหาของสตีฟไม่ได้ผล เมื่อเรียกสิ่งนี้ Close () ฟอร์มปัจจุบันจะถูกกำจัดพร้อมกับ form2 ดังนั้นคุณต้องซ่อนและตั้งค่า form2.Closed เหตุการณ์เพื่อเรียกสิ่งนี้ Close ()

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

2
ไม่มีเหตุการณ์ปิดในรูปแบบ windows ใน dot net คุณบอกฉันได้ไหมว่ามันคือเหตุการณ์ FormClosed
Anjali

2
การซ่อนรูปแบบแรกยังคงเก็บความทรงจำไว้ไม่ใช่หรือ? เราจะปล่อยทรัพยากรนั้นได้อย่างไร?
user2635088

5
form2.Closed += (s, args) => this.Close();ฉันขอทราบว่าคำสั่งนี้ทำงานอย่างไร (s,args)คืออะไรกันแน่?
Yash Saraiya

1
(s, args) => this.Close();คือการแสดงออกของแลมบ์ดา จะสร้างฟังก์ชัน "ในสถานที่" ที่ถูกเรียกใช้เมื่อform2.Closedเหตุการณ์ถูกเริ่มทำงาน (s, args)เป็นเพียงชื่อสำหรับพารามิเตอร์ของแลมด้า (object sender, EventArgs e)ซึ่งสำหรับเหตุการณ์การจัดการมักจะมีสิ่งที่ต้องการ เนื่องจากClosedลายเซ็นของผู้ร่วมกิจกรรมอธิบายประเภทของพวกเขาจึงไม่มีการกำหนดประเภท (โปรดแก้ไขข้อความของฉันหากจำเป็น) // โดยรวมแล้วเป็นวิธีที่ยุ่งยากในการไม่ต้องประกาศฟังก์ชันทั้งหมด (ตัวจัดการเหตุการณ์) นอกฟังก์ชันปัจจุบันที่จัดการForm2.Closedเหตุการณ์
KDecker

1
เพิ่ง
ซ่อนรูป

25

ลองทำตามนี้ ...

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

นี่คือสิ่งที่ ฉันมีแบบฟอร์มหลัก แต่ฉันใช้แบบฟอร์มเล็กน้อยสำหรับการเข้าสู่ระบบ แบบฟอร์มนี้เรียกฟอร์มหลักด้วยวิธีนี้ โอเคเราสบายดีที่นี่ ปัญหาคือเมื่อฟอร์มหลักแสดงแบบฟอร์มย่อยและเมื่อปิดแบบฟอร์มย่อย ... มันจะปิดฟอร์มหลักด้วย ดังนั้นเนื่องจากฉันใช้วิธีการที่ Nihique เผยแพร่ รหัสใช้งานได้ดีมาก! ...
MontDeska

รหัสนี้ใช้งานได้สำหรับฉัน ฉันใช้ VS 2015 ขอบคุณ
IT Vlogs

22

คำตอบอื่นได้อธิบายไว้หลายวิธีแล้ว อย่างไรก็ตามหลายคนมีส่วนเกี่ยวข้องShowDialog()หรือform1อยู่อย่างเปิดเผย แต่ซ่อนเร้น วิธีที่ดีที่สุดและเข้าใจง่ายที่สุดในความคิดของฉันคือเพียงแค่ปิดform1แล้วสร้างform2จากสถานที่ภายนอก (กล่าวคือไม่ใช่จากภายในรูปแบบใดรูปแบบหนึ่ง) ในกรณีที่form1ถูกสร้างขึ้นในMain, form2ก็สามารถสร้างขึ้นโดยใช้Application.Runเช่นเดียวกับform1ก่อน นี่คือสถานการณ์ตัวอย่าง:

ฉันต้องการให้ผู้ใช้ป้อนข้อมูลรับรองเพื่อให้ฉันตรวจสอบสิทธิ์ได้ หลังจากนั้นหากการรับรองความถูกต้องสำเร็จฉันต้องการแสดงแอปพลิเคชันหลักให้ผู้ใช้เห็น เพื่อให้บรรลุเป้าหมายนี้ฉันใช้สองรูปแบบ: LogingFormและMainForm. 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

เป็นเรื่องดี แต่ฉันคิดว่ามันเหมาะสำหรับ 2 รูปแบบเท่านั้น แล้วหลายรูปแบบจะสลับไปมาได้อย่างไร
ดร. MAF

สิ่งนี้ถูก จำกัด ให้เรียกใช้แบบฟอร์มตามลำดับไม่ใช่แบบขนานหรือซ้อนทับกันตามที่ OP ขอ ฉันไม่แน่ใจว่าเหตุใดจึง จำกัด เพียง 2 รูปแบบเท่านั้น รหัสภายนอกสามารถวางไข่ได้หลายรูปแบบตามลำดับที่ต้องการ การสลับระหว่างรหัสภายนอกสามารถทำได้โดยใช้รหัสภายนอก สามารถตรวจสอบสถานะบางอย่างในฟอร์มหลัก (เช่นloginForm.UserSuccessfullyAuthenticatedก่อนหน้านี้) หรืออาจจะเป็น global state เพื่อตัดสินใจว่าจะเรียกใช้ฟอร์มการเข้าสู่ระบบอีกครั้งหรือเรียกใช้แบบฟอร์มอื่นหรืออาจยุติกระบวนการ
Manuzor

11

ปัญหาเกิดจากบรรทัดนั้น:

Application.Run(new Form1()); ซึ่งอาจพบได้ในไฟล์ program.cs ของคุณ

บรรทัดนี้ระบุว่า form1 คือการจัดการกับลูปข้อความกล่าวอีกนัยหนึ่งคือ form1 มีหน้าที่ดำเนินการแอปพลิเคชันของคุณต่อไปแอปพลิเคชันจะปิดเมื่อปิด form1

มีหลายวิธีในการจัดการกับปัญหานี้ แต่ทั้งหมดไม่ทางใดก็ทางหนึ่งจะไม่ปิด form1
(ยกเว้นกรณีที่เราเปลี่ยนประเภทโครงการเป็นอย่างอื่นที่ไม่ใช่แอปพลิเคชันแบบฟอร์ม windows)

สิ่งที่ฉันคิดว่าง่ายที่สุดสำหรับสถานการณ์ของคุณคือการสร้าง 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 ของฉันสร้างคุณสมบัติสาธารณะที่เริ่มต้นเป็นเท็จและตั้งค่าเป็นจริงเฉพาะเมื่อการเข้าสู่ระบบสำเร็จเกิดขึ้น:

    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

ฉันมักจะทำสิ่งนี้เพื่อสลับไปมาระหว่างแบบฟอร์ม

ประการแรกในไฟล์Programฉันเก็บ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
}

มันจะไม่ทำงาน ไม่มีความรู้สึกที่จะซ่อนก่อนที่จะแสดงฟอร์มต่อไป มันจะดำเนินการ sametime และโปรแกรมจะถูกยกเลิก
Ahmet Karabulut



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 คำตอบ
Edward

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 และในตัวเลือกการคลิกเขียนโค้ดด้านล่าง:

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.