4

新しいフォーミュラを開くときに、フォーミュラを閉じようとしています。フォーミュラを閉じるときに、クロージングイベントでいくつかの特別なロジックを処理したいと思います。ただし、FormClosingイベントでもClosingイベントでも、抽象基本クラスでも、指定された手動で添付されたイベントでも、終了イベントが呼び出されることはありませんform_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);
    }
 }
4

4 に答える 4

6

これは、ネイティブの Windows MDI 実装が MDI 子ウィンドウの非表示をサポートしていないため、正しく動作しません。Winforms は Hide() を引き続きサポートするためにトリックを使用します。実際にはネイティブ ウィンドウを破棄し、Show() を再度呼び出すと再作成します。ただし、これには副作用があります。ネイティブ ウィンドウは Hide() 呼び出しによって既に破棄されているため、Close() 呼び出しは FormClosing/Closed イベントを発生させなくなります。これはバグであり、Winforms では珍しくありません。

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

于 2012-01-09T17:48:21.303 に答える
1

さて私は戦い続け、解決策を見つけました

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

これはWindowsフォームです。

于 2012-01-09T17:10:19.910 に答える
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 {

いずれにせよ、それは回避策であると考えてください。主な違いは、Disposed からバックアップとして呼び出されe.Cancel=trueた場合、setは効果がないことです。FormClosing

于 2013-01-05T21:52:49.433 に答える
0

これを試すことができます:

form1.Closing += delegate 
{
  // your logic
};
于 2012-01-09T17:04:18.837 に答える