Перейти к содержимому

Как закрыть все дочерние формы c

  • автор:

Как закрыть все дочерние формы c

Регистрация: 25.08.2008

Сообщений: 51

Как закрыть дочерние формы

Есть Главная форма, в ней есть menu strip по нажатию на элементы которого открываются дочерние формы в главной форме.
Но Открыв например одну дочернюю форму, хотелось бы чтобы нажав на другой элемент menu strip открывалась новая поверх старой, либо старая закрывалась.

Код главной формы выглядит так:

 private void Form1_Load(object sender, EventArgs e) < DB_Connection f = new DB_Connection(); f.TopLevel = false; f.FormBorderStyle = FormBorderStyle.None; f.Parent = this; f.Show(); >private void клиентаToolStripMenuItem_Click(object sender, EventArgs e) < ADD_DEL_Client f = new ADD_DEL_Client(); f.TopLevel = false; f.FormBorderStyle = FormBorderStyle.None; f.Parent = this; f.Show(); >private void доктораToolStripMenuItem_Click(object sender, EventArgs e)

Form. Form Closing Событие

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

Происходит перед закрытием формы.

public: event System::Windows::Forms::FormClosingEventHandler ^ FormClosing;
public event System.Windows.Forms.FormClosingEventHandler FormClosing;
public event System.Windows.Forms.FormClosingEventHandler? FormClosing;
member this.FormClosing : System.Windows.Forms.FormClosingEventHandler 
Public Custom Event FormClosing As FormClosingEventHandler 
Тип события

Примеры

В следующем примере показано использование этого элемента. В этом примере обработчик событий сообщает о возникновении FormClosing события. Этот отчет поможет вам узнать, когда происходит событие, и поможет вам в отладке. Чтобы сообщить о нескольких событиях или о событиях, которые происходят часто, рекомендуется заменить MessageBox.ShowConsole.WriteLine сообщение или добавить его в многостроочный TextBox.

Чтобы выполнить пример кода, вставьте его в проект, содержащий экземпляр типа Form с именем Form1 . Затем убедитесь, что обработчик событий связан с событием FormClosing .

private void Form1_FormClosing(Object sender, FormClosingEventArgs e) < System.Text.StringBuilder messageBoxCS = new System.Text.StringBuilder(); messageBoxCS.AppendFormat("= ", "CloseReason", e.CloseReason ); messageBoxCS.AppendLine(); messageBoxCS.AppendFormat(" = ", "Cancel", e.Cancel ); messageBoxCS.AppendLine(); MessageBox.Show(messageBoxCS.ToString(), "FormClosing Event" ); > 
Private Sub Form1_FormClosing(sender as Object, e as FormClosingEventArgs) _ Handles Form1.FormClosing Dim messageBoxVB as New System.Text.StringBuilder() messageBoxVB.AppendFormat(" = ", "CloseReason", e.CloseReason) messageBoxVB.AppendLine() messageBoxVB.AppendFormat(" = ", "Cancel", e.Cancel) messageBoxVB.AppendLine() MessageBox.Show(messageBoxVB.ToString(),"FormClosing Event") End Sub 

Комментарии

Событие FormClosing возникает при закрытии формы. При закрытии формы она удаляется, освобождая все ресурсы, связанные с формой. Если отменить это событие, форма останется открытой. Чтобы отменить закрытие формы, задайте Cancel для свойства объекта , переданного FormClosingEventArgs обработчику событий, значение true .

Если форма отображается как модальное диалоговое окно, нажатие кнопки Закрыть (кнопка с X в правом верхнем углу формы) приводит к скрытию формы, а DialogResult свойству — значение DialogResult.Cancel . Вы можете переопределить значение, присвоенное свойству DialogResult , когда пользователь нажимает кнопку Закрыть , задав DialogResult свойство в обработчике FormClosing событий для события формы.

При вызове Close метода в , отображаемом Form как немодированное окно, нельзя вызвать Show метод , чтобы сделать форму видимой, так как ресурсы формы уже освобождены. Чтобы скрыть форму и сделать ее видимой Hide , используйте метод .

Если форма является родительской формой FormClosing многодокументного интерфейса (MDI), события всех дочерних форм MDI вызываются перед событием родительской FormClosing формы MDI. Аналогичным образом события FormClosed всех дочерних форм MDI вызываются перед событием FormClosed родительской формы MDI. Отмена FormClosing события дочерней формы MDI не препятствует возникновению FormClosing события родительской формы MDI. Однако при отмене события будет задано true Cancel свойство FormClosingEventArgs класса , которое передается в качестве параметра в родительскую форму. Чтобы принудительно закрыть все родительские и дочерние формы MDI, присвойте свойству Cancel значение false в родительской форме MDI.

Дополнительные сведения об обработке событий см. в разделе Обработка и вызов событий.

Как закрыть главную форму при открытии дочерней?

Если в Visual Studio создать новый WinForms проект и посмотреть код в файле Program.cs, можно увидеть что приложение запускается вот такой строчкой:

Application.Run(new Form1()); 

Этот код неявно создает новый экземпляр ApplicationContext, который подписывается у переданной формы на событие FormClosed. Когда возникает событие FormClosed , ApplicationContext вызывает метод Application.ExitThread, который закрывает все окна и завершает приложение.

Можно сделать свой собственный ApplicationContext, что позволяет управлять жизненным циклом приложения по своему усмотрению. Вот такое приложение, например, никогда самостоятельно не завершается, его нужно будет завершать из диспетчера задач.

public class MyApplicationContext :ApplicationContext < public MyApplicationContext(Form startupForm) < startupForm.Show(); >> // .. Application.Run(new MyApplicationContext(new Form1())); 

Для того, чтобы завершить приложение тогда и только тогда, когда закроется самая распоследняя форма, можно использовать свойство Application.OpenForms для проверки наличия хотя бы одной открытой формы.

public class MyApplicationContext :ApplicationContext < public MyApplicationContext(Form startupForm) < startupForm.FormClosed += OnFormClosed; startupForm.Show(); >private void OnFormClosed(object sender, FormClosedEventArgs e) < if (Application.OpenForms.Count >0) < foreach (Form form in Application.OpenForms) < form.FormClosed -= OnFormClosed; form.FormClosed += OnFormClosed; >> else ExitThread(); > > 

Теперь главное только следить за тем, чтобы у пользователя была возможность закрыть все формы. Нельзя допускать чтобы последняя форма не имела кнопки в правом верхнем углу и не обрабатывала Alt+F4.

Однако, если применить описанный выше подход в вашем примере, он все равно не сработает.

    Вы закрываете вызывающую форму в конструкторе дочерней. В этот момент дочерняя форма все еще не открыта, и Application.OpenForms окажется пустым, что приведет к завершению приложения.
    Можно перенести код, закрывающий вызывающую форму в метод OnShown .

public partial class Form2 : Form < private Form PrevForm; private Form2() < InitializeComponent(); >public Form2(Form f) : this() < PrevForm = f; >protected override void OnShown(EventArgs e) < base.OnShown(e); PrevForm.Close(); PrevForm = null; >> 
private void simpleButton1_Click(object sender, EventArgs e) < Form2 mainForm = new Form2(this); // передаю управление дочерней форме mainForm.ShowDialog(); Close(); >

Бонус

В описанном сценарии, вам наверняка нет нужды, чтобы форма, которую вы показали первоначально, оставалась висеть в памяти после ее закрытия. Однако, Form1 это локальная переменная метода Main . Ссылка на Form1 будет хранится на стеке до тех пор, пока приложение не завершатся.

Чтобы не создавать локальную переменную, можно изменить MyApplicationContext таким образом, что он будет самостоятельно создавать самую первую форму в своем конструкторе. Например, передать в конструктор не экземпляр формы, а ссылку на метод, который этот экземпляр может создать.

public MyApplicationContext(Func formFactory) < Form startupForm = formFactory(); startupForm.FormClosed += OnFormClosed; startupForm.Show(); >// .. Application.Run(new MyApplicationContext(() => new Form1())); 

Постскриптум

Идея в том, что приложение начинается с формы ввода логина и пароля, эта форма появляется первой, а значит главная. После нажатия баттона Log In форма ввода логина и пароля исчезает и появляется основное окно.

public class MyApplicationContext :ApplicationContext < public MyApplicationContext() < Form loginForm = new LoginForm(); loginForm.UserCancelledLogin += OnUserCancelledLogin; loginForm.UserAuthorized += OnUserIsAuthorised; >private void OnUserCancelledLogin(object sender, EventArgs e) < ExitThread(); >private void OnUserAuthorised(object sender, EventArgs e) < Form loginForm = (Form)sender; loginForm.Close(); Form mainForm = new MainForm(); mainForm.FormClosed += OnformClosed(); mainForm.Show(); >private void OnFormClosed(object sender, FormClosedEventArgs e) < ExitThread(); >> 

Лучшие практики. Как закрыть главную форму из дочерней?

После запуска программы появляется окно в поле ввода логина и пароля (LoginForms), при нажатии кнопки войти (если логин и пароль верные) открывается другое окно с функционалом программы, а окно с логином и паролем закрывается.

Какое решение здесь лучшее ? Мне на ум только приходит закрытие LoginForms после нажатия на кнопку войти.

  • Вопрос задан более трёх лет назад
  • 1124 просмотра

Комментировать
Решения вопроса 1

mindtester

# @mindtester Куратор тега C#
http://iczin.su/hexagram_48

1 — не обязательно делать «логин» главной формой. можно стартовать главную форму скрытой, а форму логина дочерней, но показывать раньше, и дальше действовать в зависимости от успешности логина

2 — конкретно в WinForms можно отрабатывать вообще разные формы последовательно

using System; using System.Windows.Forms; namespace X < internal static partial class Y < /// /// Главная точка входа для приложения. /// [STAThread] static void Main() < Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(A = new fmA()); // bla-bla-bla with login Application.Run(B = new fmB()); >internal static fmA A; internal static fmB B; > >

3 — для WPF не подскажу, но наверняка оба подхода можно рассмотреть и пробовать искать аналогии

ps для WinForms

Как закрыть главную форму из дочерней?

буквальный ответ — ни как, закрытие главной формы, это завершение Application.Run(A = new fmXXX()); и если вы не модифицирутете код Main — тогда это завершение программы

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *