10

破棄されたオブジェクトにアクセスできませんというエラー メッセージが表示されます。オブジェクト名: 'ApplicationProperties'。フォームを閉じた後に再度開こうとしたとき。これはフォームの終了によるものであり、終了はフォームの「破棄」であることに気付いたので、すべての承認ボタンとキャンセル ボタン (フォームを閉じるボタン) に次のコードを追加しました。

 this.Hide(); 
 this.Parent = null;

このコードはフォームを隠しているだけです。フォームを閉じません。

私の問題は、フォームの「x」ボタンをクリックしてから、フォームを再度開こうとすると、まだエラーメッセージが表示されることです。次のようなフォームの既存の機能を変更するために、いくつかの異なる方法を試しました。

    private void ApplicationProperties_FormClosing(object sender, FormClosingEventArgs e)
    {
        //Hiding the window, because closing it makes the window unaccessible.
        this.Hide();
        this.Parent = null;
    }

しかし、これは私に運をもたらしませんでした。誰かがこの問題を解決する方法を知っているかどうか疑問に思っていました。これは、キャンセル ボタンと同意ボタン内で機能しているコードです。フォームを閉じるすべてのボタンで同じです。

    private void OptionsCancelbtn_Click(object sender, EventArgs e)
    {
        //Hiding the window, because closing it makes the window unaccessible.
        this.Hide();
        this.Parent = null;
    }

form1 のクラスの先頭でインスタンスを宣言し、form1 内に form2 を開くボタンを配置しました。

public partial class MainBox : Form
{
    //Making a name for the ApplicationProperties form. It can be opened when called.
    ApplicationProperties ApplicationPropertiesWindow = new ApplicationProperties();
    private void ApplicationPropertiesbtn_Click(object sender, EventArgs e)
    {
        //Show the properties window.
        ApplicationPropertiesWindow.Show();
    }//End ApplicationProperties button.
 }

2 番目のフォームで「x」ボタンを使用してプログラムを閉じた後、エラー メッセージが発生するため、再び form2 にアクセスできません。ApplicationPropertiesWindow.Show();

form2 内には、次のコードがあります。

public partial class ApplicationProperties : Form
{
    //Creates and sets the instance MainBoxWindow.
    public MainBox MainBoxWindow { get; set; }
4

4 に答える 4

6

FormClosingあなたのイベントでこれを試してください:

  private void ApplicationProperties_FormClosing(object sender, FormClosingEventArgs e)
  {
        //Hiding the window, because closing it makes the window unaccessible.
        this.Hide();
        this.Parent = null;
        e.Cancel = true; //hides the form, cancels closing event
   }

現在もフォームを閉じているため、エラーが発生しています。

于 2013-08-02T16:39:19.040 に答える
5

2 番目のフォームで「x」ボタンを使用してプログラムを閉じた後、エラー メッセージが発生するため、再び form2 にアクセスできません。 ApplicationPropertiesWindow.Show();

フォームが閉じられると ( Form.Close)、フォーム自体とそれに関連付けられているすべてのリソースが解放されます。ドキュメントに記載されているように、この自動破棄には 2 つの例外があります。

  1. フォームは MDI アプリケーションの一部であり、表示されません。
  2. ShowDialogフォームは( ではなく)を使用してモーダル ダイアログとして表示されましたShow。このように設計されているため、ユーザーがダイアログを閉じた後、ダイアログのプロパティにアクセスできます (たとえば、ユーザー入力を取得するため)。

Disposeこれらの特殊なケースの両方で、フォームのメソッドを手動で呼び出す必要があります。2 番目のケースは最も一般的で (MDI パラダイムを実際に使用する人はもう誰もいません)、次のusingステートメントで簡単に処理できます。

using (MyDialogBox dlg = new MyDialogBox())
{
    DialogResult result = dlg.ShowModal(this);
    if (result == DialogResult.Yes)
    {
        // access members of "dlg", and
        // do whatever the user asked
    }
}  // the Dispose method is automatically called here

あなたの場合、典型的なように、Closeメソッドへの呼び出しはフォームを閉じて破棄しています。破棄されたオブジェクトにアクセスできないことは既にわかっています (存在しないためです!)。そのため、表示しようとすると例外が発生します。フォームを閉じた後に再度表示するには、フォーム クラスの新しいインスタンスを作成する必要があります。

MyForm frm = new MyForm();
frm.Show();
// ...
frm.Close();

これは本当に最善の方法です。フォームの新しいインスタンスは、同じクラスから作成されているため、閉じているものと同じになります。オブジェクト指向の観点から考え始め、可能な限りシングルトン ベースの設計を避けることをお勧めします。画面に表示される各フォームは、新しい独立したオブジェクトです。そのオブジェクトが閉じられて破棄されると、それは使用できなくなります。再度使用する場合は、新しいオブジェクトを作成して表示する必要があります。

メソッドはハックのHideようなもので、フォームの現在のインスタンスを一時的に非表示にし、その状態 (メンバー プロパティの値、コントロールの状態など) を保持したい場合にのみ役立ちます。これは、破棄されることのないシングルトン オブジェクトでのみ機能し、慎重に設計および保守する必要があります。また、このフォーム オブジェクトは、使用されているかどうかにかかわらず、常にリソースを消費することを意味し、これは無駄です。

これを行う必要がある場合は、フォーム インスタンスが破棄される原因を追跡する必要があります。あなたのコードをすべて見なければ、問題がどこにあるのかを推測する以外に何もすることはできません。AcceptButtonand/orCancelButtonプロパティの使用に関連している可能性があります。いずれにせよ、最善かつ最もクリーンな解決策は、OnFormClosingメソッドをオーバーライドして、フォームが閉じられないようにすることです。代わりに非表示にします。

public class MyForm : Form
{
    protected virtual void OnFormClosing(FormClosingEventArgs e)
    {
        // Prevent the form from closing.
        e.Cancel = true;

        // Hide it instead.
        this.Hide();
    }

    // ...other code in your form class
}    

これの利点は、外部コードに公開されてアプリケーション全体に散在するのではなく、責任のあるクラスに対してローカルな1か所にコードを配置するだけでよいことです。そしてもちろん、制御外のフレームワーク コードによってフォームが閉じられることも防ぎます。

Parentプロパティを に設定する理由がわかりませんnull。トップレベル ウィンドウ (すべてのフォームがそうであるもの) は、親を持つことはできません。子ウィンドウ (コントロールなど) だけが親を持ちます。所有者を持つことができますが、必ずしもそうであるとは限りません。メソッドを呼び出すときに、オーナー ウィンドウを引数として渡すかどうかによって異なりますShow

于 2013-08-03T05:28:04.853 に答える
3

問題の少なくとも一部は、クラスの相互依存関係のように見えます。

ApplicationPropertiesインスタンスを初期化すると、MainBoxオブジェクトへの参照が作成されますが、クラスの定義では、 ... を参照MainBoxする新しいApplicationsPropertiesオブジェクトが作成されます。MainBoxアプリケーションの起動時に読み込まれるのは、親フォームですかMainBox?

MainBoxクラスでそれへの参照を設定すると、不注意に一部のものが破棄されても驚かないでしょうApplicationProperites...「X」をクリックすると破棄されます。繰り返しますが、これは経験に基づいた推測です。それが理由かどうかはわかりませんが、コード自体は間違っていなくても、私には風変わりに見えます。

ApplicationPropertiesウィンドウを永遠に維持し、物事を簡素化したい場合は、アプリケーションの期間を永続化するフォームの先頭でウィンドウの静的インスタンスを初期化し、最初に試みていたものと同様に表示/非表示にします。効率的かつ基本的なものにしたい場合はApplicationProperties、ユーザーが変更できるようにする必要があるときはいつでも構築して破棄しますが、循環依存関係を破棄します。

于 2013-08-02T20:21:08.630 に答える