2

以下の問題を解決するのに助けが必要です。

MDI インターフェイスを使用して Windows フォーム アプリケーションを作成しています。私のアプリケーションでは、基本的にすべての子フォームのすべての開閉を処理するクラスを作成しました。これをFManageと呼びましょう。さらに、フォーム インスタンスが開いているかどうかもチェックします。その場合、ユーザーはフォームの別のインスタンスを開くことができません。ここに私の問題があります。ユーザーがウィンドウを開くように求められた場合、FManageは次のコードを実行します。

if (frm1 == null)
{
    frmOne = new frm1();
    frmOne.MdiParent = Main.ActiveForm; //Main is the parent form
}
frmOne.Show();

ウィンドウが最初に開かれたときに、このコードが正常に機能するようになりました。frm1が閉じられ、再度開くように求められたとします上記のコードが再度実行されますが、frm1は NULL と等しくありません。FManageクラスの上記のコードにブレーク ポイントを設定したところ、 frm1が閉じられていても、 frm1 != nullが表示されます。問題は、frm1がFManageに参照として格納されているため、FManageが null であることを伝えていないことだと思います。FManageは、静的変数と同様に、フォームの初期状態を格納するだけです。私はOOPが初めてで、この問題を解決する最善の方法を本当に探しています.

私の最初の解決策は、おそらく FormClosing イベントでfrm1が閉じる前に、メッセージをFManageクラスに送り返してfrm1を null に設定することです。ただし、これを行うには、frm1クラスがFManageについて知る必要がありますが、現在はそうではありません。FManageはfrm1について知っていますが、その逆ではありません。共有は相互ではありません。参考までに、クラスが定義された後にfrm1がメソッドとして定義されます。

public class FManage
{
    frmOne frm1;
 ...
}

この問題を解決する方法についての提案は大歓迎です。

4

7 に答える 7

6

問題を解決する鍵は、FormClosing イベントのサブクラス化です。
フォームを開いたときに、そのイベントのハンドラーを設定します。
次に、そのイベントで (閉じることに同意する場合)、グローバル変数を null に設定します。
これにより、ロジックが正しくリセットされ、frmOne の新しいインスタンスが開きます。
frmOne (クラス) と frm1 (frmOne のインスタンス) を混同しないでください。

public class FManage 
{ 
    frmOne frm1; 
    ... 

    // Here test on frm1 and create a new instance of frm1
    if (frm1 == null) 
    { 
        frm1 = new frmOne(); 
        frm1.FormClosing += fManage_FormOneClosing;
        frm1.MdiParent = Main.ActiveForm; 
    } 
    frm1.Show(); 

    ...

    public void fManage_FormOneClosing(object sender, FormClosingEventArgs e) 
    {
        ... (check if you agree to close the form frm1

        // set the instance of frmOne captured in the global var to null....
        frm1 = null;
    }
} 
于 2012-05-10T17:59:20.540 に答える
2

AFormは、他のオブジェクトと同じようにオブジェクトです。その存続期間は、まだ到達可能かどうかによって制御されます。したがって、フォームを非表示 (閉じる) しても、オブジェクトが破棄されたり、何かが に設定されたりすることはありませんnull

フォームがいつ閉じられたかを知るには、フォームのFormClosedイベントを処理する必要があります。

于 2012-05-10T17:50:54.100 に答える
1

MSDN から:

フォームが閉じられると、オブジェクト内で作成されたすべてのリソースが閉じられ、フォームが破棄されます。Closing イベントを処理し、パラメーターとしてイベント ハンドラーに渡された CancelEventArgs の Cancel プロパティを設定することにより、実行時にフォームが閉じないようにすることができます。閉じようとしているフォームがアプリケーションのスタートアップ フォームである場合、アプリケーションは終了します。

Close でフォームが破棄されない 2 つの条件は、(1) マルチ ドキュメント インターフェイス (MDI) アプリケーションの一部であり、フォームが表示されない場合です。(2) ShowDialog を使用してフォームを表示しました。このような場合、Dispose を手動で呼び出して、フォームのすべてのコントロールにガベージ コレクションのマークを付ける必要があります。

于 2012-05-10T17:52:59.607 に答える
1

1 つのオプションは、説明したように FormClosing イベントを処理することです。FManage について「知る」ためにフォームは必要ありません。次のように、FManage をイベントにサブスクライブさせることができます。

frm1.FormClosing += this.FormClosing; // this is FManage

もう 1 つのオプションは、子フォームを作成するときに、フォームの Visible プロパティが true かどうかを確認することです。

if (frmOne == null || !frmOne.Visible)
{
    frmOne = new frm1();
    frmOne.MdiParent = Main.ActiveForm; //Main is the parent form
}
else
{
    // form is already created.  maybe bring to front?
    frmOne.BringToFront();
}
于 2012-05-10T17:54:21.027 に答える
0

もう1つの解決策は、My.Application.OpenFormsコレクションを反復処理して、フォームが開いているかどうかを確認することです。
それらは、onFormClosed内部メソッド/イベントが呼び出されると、このコレクションから削除されます。

于 2012-11-09T16:55:44.940 に答える
0

ラムダを使用できます:

public class FManage 
{ 
    frmOne frm1; 
    ... 

    // Here test on frm1 and create a new instance of frm1
    if (frm1 == null) 
    { 
        frm1 = new frmOne(); 
        frm1.FormClosing += (sndr, evnt) => { frm1 = null; };
        frm1.MdiParent = this; 
    } 
    frm1.Show(); 

    ...

} 
于 2014-06-05T07:27:08.853 に答える
0

frmOne がスコープ外に渡されていない場合は、破棄されません。指定した値が保持されます (この場合は frm1 のインスタンス)。必要に応じて、表示する必要があるたびに新しい frm1 オブジェクトを作成できます。

于 2012-05-10T17:53:14.160 に答える