11

FormClosingイベントを使用すると、コードはe.Cancel = true;機能するのに機能しないのはなぜnew CancelEventArgs().Cancel = true;ですか?

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    e.Cancel = true;

    new CancelEventArgs().Cancel = true;
}
4

4 に答える 4

23

このイベントは、Winforms配管コードによって発生します。カスタムイベントハンドラーがデフォルトの動作を変更したいことを確認できる唯一の方法は、eオブジェクトを使用することです。新しいCancelEventArgsオブジェクトを作成しても、配管で検出できる副作用はありません。

他に何か問題があります。外部コードの利益のためにイベントが発生し、何が起こっているのかを知らせ、動作を変更するオプションを提供します。ここには外部コードはありません。イベントハンドラーは、実際にはイベントを発生させる同じクラスの一部です。つまり、フォームは独自のイベントをリッスンしています。これに対処するためのはるかに優れた方法があります。イベントを発生させるメソッドをオーバーライドします。このような:

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

これで、外部コードがデフォルトの動作をオーバーライドできるようになり、OnXxxxメソッドの実行後にイベントが発生します。また、外部コードで動作をオーバーライドしたくない場合は、2つのステートメントを入れ替えるだけです。

于 2011-02-28T13:55:50.247 に答える
15

コードはそれが言っていることを正確に実行していると思います。欠けているのはそれを文字通り読むことです。

に新しい値を割り当てると、関数のパラメーターとして提供されるをe.Cancel変更することになります。eイベントハンドラー関数が終了FormClosingEventArgsすると、イベントハンドラー内から加えられた変更を含め、このインスタンスは、イベントハンドラーを呼び出したすべてのコードで使用できるようになります。この場合、それはほぼ確実にMicrosoftによって作成されたWinformsコードです。

反対に、そのイベントハンドラーでその型の新しいインスタンスを作成し、FormClosingEventArgsそれに何かを行うと、その情報を呼び出し元に返すことはできません。そのためには何か明確なものが必要です。呼び出し元は、イベントハンドラーが完了すると渡されたパラメーターの値を確認しているため、呼び出し元からe見た内容を新しく作成されたインスタンスに置き換える必要があります。その他の場合、そのような結果は戻り値として提供される場合があります。

一般に、new T()あるタイプのの結果は、タイプTのインスタンスですTnew T()したがって、型のnull以外の変数と同じように、式の結果を操作できますTT特定のケースでは、タイプのプロパティ(具体的には、このように作成されたタイプのインスタンス)に値を割り当てています。(コンストラクターが失敗する特殊なケースがありますが、今はそこに行きません。単純な型の場合、それは、プログラムがどのような場合でも実行を継続できないほどの悲惨な状況にあることを意味します。 )。

new T() ここで重要なのは、式自体の結果をどこにも割り当てない場合、ステートメントが完了すると、新しく作成されたインスタンスが破棄される(技術的にはアクセスできなくなる)ことです。その後、ある時点で、.NETガベージコレクタが起動し、割り当てられたメモリを実際に再利用します。ここを除いて、ある関数に変数を割り当て、別の関数からその関数を呼び出し、最初の関数から2番目の関数に変数を転送することなく、2番目の関数から割り当てられた変数にアクセスしようとすることと実際には何の違いもありません。関与する機能は1つだけです。

イベントハンドラーで2行目のコードのようなことを行うのはかなり珍しいことですが、コンストラクターを呼び出すことで、遅延読み込みのトリガーなど、利用しようとしている副作用がある場合は、原則として有効です

于 2011-02-28T13:24:59.887 に答える
6

このコードは確かに機能します

protected override void OnFormClosing(FormClosingEventArgs e)
        {            
            base.OnFormClosing(e);
            if (PreClosingConfirmation() == System.Windows.Forms.DialogResult.Yes)
            {
                Dispose(true);
                Application.Exit();
            }
            else
            {
                e.Cancel = true;
            }
        }

        private DialogResult PreClosingConfirmation()
        {
            DialogResult res = System.Windows.Forms.MessageBox.Show(" Do you want to quit?          ", "Quit...", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            return res;
        }

ハッピーコーディング

于 2013-02-21T07:54:30.823 に答える
3

これCancelEventArgsは、コード内のイベント ハンドラーに渡されるオブジェクト参照であるためです。舞台裏のコードがオブジェクトで発生FormClosingし、CancelEventArgsすべてのイベント ハンドラーが同じオブジェクトを受け取ります。すべてのハンドラーの順番が回ったら、バックグラウンド コードがCancelEventArgs送信したオブジェクトをチェックして、そのCancelプロパティが に設定されているかどうかを確認しますtrue。そうであれば、何もせず、FormClose一連のイベントが停止します。Cancelfalse (CancelEventArgs既定値) の場合、つまりイベントCancelチェーンに設定されていない場合、舞台裏のコードが処理され、FormClosedイベントが発生します。

詳細については、MSDN の Form.FormClosing Event を参照してください

通常、Formsすべての -ing イベントの後に -ed イベントが続きます。-ing イベントには通常 がありCancelEventArgs、そのCancelプロパティを に設定しtrueて -ed イベントの発生を停止できます。

于 2013-05-03T17:36:52.160 に答える