2012-01-09 2 views
4

Я пытаюсь закрыть формуляр при открытии нового. Закрывая формуляр, я хочу обработать некоторую специальную логику в событии закрытия. Но закрывающее событие никогда не вызывается, ни в событии FormClosing, ни в закрытии, ни в абстрактном базовом классе, ни в данном заданном вручную подключенном событии form_FormClosing.Событие FormClosing, не вызванное дочерней формой MDI

Когда я вручную закрываю форму, щелкнув x, все события уволены в порядке. Вызов метода Close() завершается с ошибкой.

Есть ли у вас рекомендации по исправлению проблемы?

MdiParent:

private Form _currentForm; 
private void ShowForm<T>() where T : Form 
{ 
    if (_currentForm != null && !_currentForm.IsDisposed) 
    { 
     _currentForm.Hide(); 
     _currentForm.Close(); 
    } 

    var form = MdiChildren.FirstOrDefault(f => f.GetType() == typeof(T)); 
    if (form == null) 
    { 
     form = _formFactory.CreateForm<T>(); 
     form.MdiParent = this; 
     form.WindowState = FormWindowState.Maximized; 
     form.FormClosing += form_FormClosing; 
     _currentForm = form; 
     MdiBackground.Hide(); 
     form.Show(); 
    } 
    else 
    { 
     ActivateMdiChild(form); 
     form.Activate(); 
    } 
} 

void form_FormClosing(object sender, FormClosingEventArgs e) 
{ 
    // will not be called 
} 

Абстрактная форма родовой МДИ ребенок:

public abstract partial class BaseForm<TEntity> : Form where TEntity : class, IEntity 
{ 
    protected override void OnClosing(CancelEventArgs e) 
    { 
     // wil not be called 
     if (EditMode == EditModes.Editable) 
     { 
      MessageBox.Show(this, "Please commit or abort your changes"); 
      e.Cancel = true; 
     } 
     base.OnClosing(e); 
    } 
} 

ответ

6

Это неверно, поскольку встроенная реализация Windows MDI не поддерживает скрытие дочерних окон MDI. Winforms использует трюк для поддержки Hide(), он фактически разрушает собственное окно и воссоздает его, когда вы снова вызываете Show(). Это имеет побочный эффект, однако вызов Close() больше не вызывает события FormClosing/Closed, поскольку собственное окно уже было уничтожено вызовом Hide(). Это ошибка, не редкость в Winforms.

Обходной путь прост, вам не нужно скрывать(), когда вы вызываете Close(), просто удалите его.

0

Вы можете попробовать это:

form1.Closing += delegate 
{ 
    // your logic 
}; 
+0

Я уже сделал это. – Rookian

+0

Как насчет FormClosed()? –

+0

OH жаль, что я не понял ваш вопрос. –

1

Ну, я продолжал бороться и нашел решение

if (_currentForm != null && !_currentForm.IsDisposed) 
{ 
    // This call prevents calling the closing event -> _currentForm.Hide(); 
    _currentForm.Close(); 
} 

Это Windows Forms ._.

+0

Может ли кто-нибудь сказать мне, почему это так ведет себя? – Rookian

0

Это сообщение было полезно и мне, хотя мое дело было несколько иным.

В этом случае избегание _currentForm.Hide(); работает нормально, потому что код выполняет форму-переключатель. Я обнаружил, что проблема также связана с MDIChild, которая была скрыта другой MDIChild, которая находится сверху.

Вот обходной путь, который работает и в этом случае на основании того факта, что всегда вызывается Dispose.

Это можно сделать подготовку что-то вроде этого:

public abstract class FormExtenderClass : Form{ 
    private bool formClosingFired = false; 
    private bool formClosedFired = false; 

    protected override void OnFormClosing(FormClosingEventArgs e) { 
     base.OnFormClosing(e); 
     formClosingFired = !e.Cancel; 
    } 

    protected override void OnFormClosed(FormClosedEventArgs e) { 
     base.OnFormClosed(e); 
     formClosingFired = true; 
    } 

    protected override void Dispose(bool disposing) { 
     if (!formClosingFired) OnFormClosing(new FormClosingEventArgs(CloseReason.UserClosing, false)); 
     if (!formClosedFired) OnFormClosed(new FormClosedEventArgs(CloseReason.UserClosing)); 
     base.Dispose(disposing); 
    } 
} 

Тогда в коде MDIChildren просто изменить первую строку из

public partial class AutoForm : Form { 

в

public partial class AutoForm : FormExtenderClass { 

Считают, что это в любом случае, беспокойство. Основное различие заключается в том, что набор e.Cancel=true не будет иметь эффекта в случае, если FormClosing вызывается из Disposed as backup.

Смежные вопросы