c # открыть новую форму, а затем закрыть текущую форму?


89

Например, предположим, что я нахожусь в форме 1, тогда я хочу:

  1. Открыть форму 2 (с кнопки в форме 1)
  2. Закрыть форму 1
  3. Сосредоточьтесь на форме 2

18
Ужасное удобство использования. Если вы используете WinForms, просто создайте окно контейнера и замените вместо него панели. Ваши пользователи будут любить вас за это (и ненавидеть за то, что вы этого не делаете)
Клаус Йоргенсен

1
Слушай Клауса! Возможно, вы пытаетесь достичь: a) Winforms-реализация последовательной серии шагов, подобной мастеру, или b) попытка показать форму «результат» после формы «ввод / отправка данных». Независимо от того, а) или б) поведение пользовательского интерфейса, которое вы пытаетесь реализовать, является неоптимальным решением.
Simen S

Большое спасибо Clause и Simen S. Ваши комментарии очень полезны для такого новичка, как я. Я прочитаю больше руководств по графическому интерфейсу и удобству использования. Не могли бы вы порекомендовать мне несколько полезных?
tnhan07 06


Также проверьте [ответы здесь] ( stackoverflow.com/questions/4759334/… ), если вы действительно намеревались создать форму входа (или аналогичную).
ilias iliadis

Ответы:


193

Решение Стива не работает. При вызове 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
в формах окон в точечной сети нет события Closed. Можете ли вы сказать мне, это мероприятие FormClosed
Анджали

2
Разве скрытие первой формы не сохраняет ее в памяти? Как мы можем освободить этот ресурс?
user2635088

5
form2.Closed += (s, args) => this.Close();Могу я узнать, как работает это заявление? что именно (s,args)?
Яш Сарайя 04

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

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-х форм. А как насчет переключения между несколькими формами ??
Д-р МАФ

Это ограничивается запуском форм в последовательности, а не параллельно или поверх друг друга, как просил OP. Я не уверен, почему это должно быть ограничено только двумя формами. Внешний код может порождать столько форм, сколько необходимо. Переключение между ними также может выполняться внешним кодом. Он может проверить какое-то состояние в основной форме (как loginForm.UserSuccessfullyAuthenticatedраньше) или, возможно, глобальное состояние, чтобы решить, следует ли повторно запустить форму входа в систему или запустить другую форму, или, возможно, завершить процесс.
Манузор

11

Проблема заключается в этой строке:

Application.Run(new Form1()); Что, вероятно, можно найти в вашем файле program.cs.

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

Есть несколько способов справиться с этим, но все они так или иначе не закрывают form1.
(Если мы не изменим тип проекта на что-то другое, кроме приложения Windows Forms)

Я считаю, что проще всего в вашей ситуации создать 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

Обычно я делаю это, чтобы переключаться между формами.

Во-первых, в файле 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
}

Это не сработает. Нет смысла прятаться перед показом следующей формы. Он будет выполнен в то же время, и программа будет завершена.
Ахмет Карабулут

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
Что в этом ответе добавляет к этому обсуждению? Он повторяется без добавления какой-либо поясняющей информации, представленной в 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();

    }

Это решение не является ответом на этот вопрос. Ваше решение не закроет текущую форму, это означает, что текущая форма все еще обрабатывается.
Ахмет Карабулут

-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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.