在封闭事件中的“e.Cancel”

时间:2011-02-28 13:21:33

标签: c# .net events formclosing

使用FormClosing事件时,为什么代码e.Cancel = true;有效,但new CancelEventArgs().Cancel = true;不起作用?

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

    new CancelEventArgs().Cancel = true;
}

4 个答案:

答案 0 :(得分:22)

该事件由Winforms管道代码引发。它可以看到自定义事件处理程序想要更改默认行为的唯一方法是通过e对象。创建一个新的CancelEventArgs对象没有管道可以检测到的副作用。

还有其他错误,为了外部代码的利益而提出事件,让它知道发生了什么,并给它一个改变行为的选项。这里没有外部代码,事件处理程序实际上是引发事件的同一个类的一部分。换句话说,表单正在倾听自己的事件。有一个更好的方法来处理它,你覆盖引发事件的方法。像这样:

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

现在外部代码可以覆盖默认行为,运行OnXxxx方法后引发事件。您可以选择,如果您不希望外部代码覆盖该行为,只需交换这两个语句。

答案 1 :(得分:15)

我认为代码完全按照它的说法行事;缺少的是文字阅读。

e.Cancel分配新值时,您正在修改作为函数参数提供的e。事件处理程序函数完成后,此FormClosingEventArgs实例(包括从事件处理程序中对其进行的任何更改)将可用于调用事件处理程序的任何代码。在这种情况下,几乎可以肯定是微软编写的Winforms代码。

另一方面,当您在内部时,该事件处理程序创建了一个类型FormClosingEventArgs的新实例并对其执行某些操作,没有任何内容可以将该信息提供给调用者;你需要明确的某些东西。由于调用者在事件处理程序完成后查看它传入的参数的值,因此您需要以某种方式用新创建的实例替换调用者看到的e的内容。在其他情况下,这样的结果可能会作为返回值提供。

通常,对于某些类型new T()T的结果是T类型的实例。因此,您可以使用表达式new T()的结果,就像处理T类型的非null变量一样。在您的特定情况下,您要为类型T上的属性分配值(特别是,由此创建的该类型的实例)。 (有一种特殊情况,构造函数失败了,但是现在不要去那里;对于简单类型,这几乎意味着你处于如此困难的境地,以至于你的程序在任何情况下都不可能继续运行。 )

这里重要的是,如果你没有在任何地方分配表达式new T() 本身的结果,那么一旦声明,新创建的实例就会被抛弃(技术上,变得无法访问)完成。然后在稍后的某个时刻,.NET垃圾收集器启动并实际回收已分配的内存。它与在一个函数中分配变量,从另一个函数调用该函数并尝试访问从第二个函数分配的变量并没有做任何事情来将变量从第一个函数传递到第二个函数实际上没有任何不同,除了这里只涉及一个功能。

在事件处理程序中执行类似第二行代码的操作会很不寻常,但是如果调用构造函数有一些副作用,那么 原则上是有效的,例如触发延迟加载。

答案 2 :(得分: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;
        }

快乐编码

答案 3 :(得分:3)

这是因为CancelEventArgs是传递给代码中事件处理程序的对象引用。幕后代码使用FormClosing对象引发CancelEventArgs,并且所有事件处理程序都接收相同的对象。所有处理程序轮到后,后台代码会检查它发送的CancelEventArgs对象,以查看其Cancel属性是否设置为true。如果是,则它不会执行任何操作,FormClose事件链将停止。如果CancelfalseCancelEventArgs默认值),意味着它尚未设置为Cancel事件链,则幕后代码继续进行,然后提出FormClosed事件。

您可以在Form.FormClosing Event on MSDN了解更多信息。

Forms中,所有-ing事件通常后跟-ed事件。 -ing事件通常为CancelEventArgs,可以将Cancel属性设置为true以阻止-ed事件发生。