2012-01-09 11 views
4

新しいイベントを開くときに定型を閉じようとしています。 フォーミュラを閉じるときに、私はクローズイベントでいくつかの特別なロジックを処理したいと思います。 しかし、closingイベントは、FormClosingイベント、Closingイベント、抽象基本クラス、または手動添付のイベントform_FormClosingでは呼び出されません。MDIの子フォームでFormClosingイベントが呼び出されない

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 
} 

抽象汎用のMDI子フォーム:

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()を再度呼び出すと実際にネイティブウィンドウを破棄して再作成します。しかし、これには副作用がありますが、Hide()呼び出しによってネイティブウィンドウがすでに破棄されているため、Close()呼び出しはFormClosing/Closedイベントを発生させません。これはWinformsでは珍しいことではないバグです。

回避策は簡単ですが、Close()を呼び出すときにHide()を行う必要はありません。削除するだけです。

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フォーム._です。

+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]から呼び出された場合には効果がないことです。

関連する問題