c # відкрити нову форму, а потім закрити поточну форму?


89

Наприклад, припустимо, що я перебуваю у формі 1, тоді я хочу:

  1. Відкрити форму 2 (за допомогою кнопки у формі 1)
  2. Закрийте форму 1
  3. Зосередьтеся на формі 2

18
Жахлива юзабіліті. Якщо ви використовуєте WinForms, просто створіть вікно контейнера та замість нього замініть панелі. Ваші користувачі будуть вас любити за це (і ненавидітимуть вас за те, що ви цього не робите)
Клаус Йоргенсен,

1
Слухай Клауса! Те, що ви намагаєтесь досягти, це, можливо, a) Реалізація winform послідовних послідовних кроків, подібних до майстра, або b) Спроба показати форму "результат" після форми "введення / подання даних". Незалежно від того, а) чи б) поведінка інтерфейсу користувача, яку ви намагаєтесь реалізувати, є неоптимальним рішенням.
Simen S

Дякую Клаузу та Сімену С. Ваші коментарі дуже корисні для такого новачка, як я. Я прочитаю більше підручників про графічний інтерфейс та зручність використання. Чи можете ви порадити мені кілька корисних?
tnhan07,


Також перевірте [відповіді тут] ( stackoverflow.com/questions/4759334/… ), якщо Вашим справжнім наміром було лише мати форму входу (або подібну).
ilias iliadis

Відповіді:


194

Рішення Стіва не працює. При виклику this.Close () поточна форма розміщується разом із form2. Тому вам потрібно приховати це та встановити form2.Closed подію, щоб викликати this.Close ().

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

2
немає закритої події у віконних формах у dot net. Чи можете ви сказати мені, що це подія FormClosed
Анджалі

2
Чи не приховування першої форми все ще зберігає пам’ять? Як ми можемо випустити цей ресурс?
user2635088

5
form2.Closed += (s, args) => this.Close();Чи можу я знати, як працює це твердження? що саме (s,args)?
Яш Сарая

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. Дякую
ІТ-журнали

21

Багато різних способів вже описано в інших відповідях. Однак багато з них або залучені, 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-х форм. А як щодо кількох форм, що перемикаються між ними ??
Доктор МАФ,

Це обмежується запуском форм у послідовності, а не паралельно або одна на одній, як просив ОП. Але я не впевнений, чому це обмежується лише двома формами. Зовнішній код може створювати стільки форм у послідовності, скільки потрібно. Перемикання між ними також може здійснюватися зовнішнім кодом. Він може перевірити якийсь стан у головній формі (як loginForm.UserSuccessfullyAuthenticatedраніше) або, можливо, глобальний стан, щоб вирішити, чи потрібно повторно запускати форму для входу, чи запускати іншу форму, або, можливо, припинити процес.
Манузор

11

Проблема в цьому рядку:

Application.Run(new Form1()); Які, ймовірно, можна знайти у вашому файлі program.cs.

Цей рядок вказує, що form1 повинен обробляти цикл повідомлень - іншими словами form1 відповідає за продовження роботи вашої програми - програма буде закрита, коли form1 буде закрита.

Є кілька способів вирішити це, але всі вони тим чи іншим чином не закриють форму1.
(Якщо ми не змінимо тип проекту на щось інше, ніж додаток у формі Windows)

Я вважаю, що для вашої ситуації найлегше створити 3 форми:

  • form1 - залишатиметься невидимим і діятиме в якості менеджера; ви можете призначити його для обробки піктограми в треї, якщо хочете.

  • form2 - матиме кнопку, яка при натисканні закриє form2 і відкриє form3

  • form3 - буде виконувати роль іншої форми, яку потрібно відкрити.

І ось зразок коду для цього:
(Я також додав приклад, щоб закрити програму з третьої форми)

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, створіть загальнодоступне властивість, яке ініціалізується на false і встановлюється на true лише у випадку успішного входу:

    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

використовуйте цей фрагмент коду у вашій формі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();
}

Я отримав це звідси


Зауважте, що відповіді лише на посилання не рекомендуються, відповіді 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

Зазвичай я роблю це для перемикання між формами.

По-перше, у файлі програми я зберігаю 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
}

Це не спрацює. Немає сенсу приховуватись перед тим, як показувати наступну форму. Він буде виконаний одночасно, а програма буде припинена.
Ахмет Карабулут, 30



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 інших відповідях.
Едвард

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

    }

Це рішення не є відповідною відповіддю на це питання. Ваше рішення не закриє поточну форму, ця середня поточна форма все ще триває.
Ахмет Карабулут 30

-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(). Закриття форми розпоряджається нею, встановлення видимості форми - це те саме, що приховувати її, а приховувати форму безглуздо, коли вона не буде існувати до наступної події фарби.
Серві

-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? Чому робити те саме двічі?
Неоліск,

8
Крім того, чому ви створюєте нове Form1і нічого з ним не робите?
Серві,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.