“e.Cancel”在FormClosing事件中的作用。

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个回答

23

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

还有其他问题,事件是为外部代码服务的,让其知道正在发生什么并提供更改行为的选项。 这里没有外部代码,事件处理程序实际上是引发事件的同一类的一部分。 换句话说,窗体正在侦听其自己的事件。 处理这种情况的更好方法是覆盖引发事件的方法。就像这样:

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

现在外部代码可以覆盖默认行为,事件会在OnXxxx方法运行被触发。而且你有选择的余地,如果你不想让外部代码覆盖行为,只需交换两个语句的位置。


15
我认为这段代码正是按照它所说的在执行;缺少的是对它的直接理解。
当你为 e.Cancel 赋予一个新值时,你正在修改作为参数提供给函数的 e。事件处理程序函数完成后,包括在事件处理程序中所做的任何更改在内的 FormClosingEventArgs 实例将可用于调用事件处理程序的任何代码。在这种情况下,几乎可以肯定是由 Microsoft 编写的 Winforms 代码。
另一方面,在事件处理程序中创建类型 FormClosingEventArgs 的新实例并对其进行操作时,没有什么可以将该信息传递回调用者;你需要有明确的 某些内容 来完成这个任务。由于调用者在事件处理程序完成后查看其传入的参数的值,因此你需要以某种方式替换由调用者看到的 e 的内容,使其成为新创建的实例。在其他情况下,这样的结果可能会作为返回值提供。
通常,对于某个类型 T,表达式 new T() 的结果是类型 T 的一个实例。因此,你可以像处理类型 T 的非空变量一样处理这个表达式的结果 new T()。在你的特定情况下,你正在为类型 T 上的属性赋值(具体来说,是创建的该类型的实例)。 (有一种特殊情况,即构造函数失败,但我们现在不去深究它;对于简单类型,这几乎意味着你处于如此困境的境地,以至于你的程序不太可能能够继续运行。)
在这里重要的是,如果你没有将表达式 new T() 的结果分配给任何变量,新创建的实例将在语句完成后被丢弃(从技术上讲,变得无法访问)。然后在稍后的某个时间点,.NET 垃圾回收器会启动并实际回收分配的内存。这与在一个函数中分配变量,在另一个函数中调用该函数并尝试从第二个函数访问因此分配的变量而不执行任何传输变量的操作并没有什么区别,只是在这里只涉及一个函数。
像你在事件处理程序中的第二行代码那样做通常是相当不寻常的,但原则上是有效的,如果调用构造函数具有某些你想利用的副作用,例如触发惰性加载。

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
这是因为CancelEventArgs是一个对象引用,传递给你的代码中的事件处理程序。后台代码使用CancelEventArgs对象引发FormClosing事件,所有事件处理程序都接收到相同的对象。一旦所有处理程序完成,后台代码会检查发送的CancelEventArgs对象,看它的Cancel属性是否设置为true。如果是,则不执行任何操作,FormClose事件链停止。如果Cancelfalse(即CancelEventArgs的默认值),意味着它没有被设置为Cancel,则事件链继续进行,然后引发FormClosed事件。

你可以在MSDN上了解更多信息

Forms中,所有以-ing结尾的事件通常都有对应的以-ed结尾的事件。-ing事件通常具有CancelEventArgs,该对象的Cancel属性可以设置为true,以阻止-ed事件的发生。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接