简体   繁体   English

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

[英]“e.Cancel ” in formclosing Event

When using the FormClosing event, why does the code e.Cancel = true; 使用FormClosing事件时,为什么代码e.Cancel = true; work, but new CancelEventArgs().Cancel = true; work,但是new CancelEventArgs().Cancel = true; does not work? 不起作用?

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

    new CancelEventArgs().Cancel = true;
}

The event is raised by the Winforms plumbing code. 该事件由Winforms管道代码引发。 The only way it can see that the custom event handler wants to alter the default behavior is through the e object. 它可以看到自定义事件处理程序想要更改默认行为的唯一方法是通过e对象。 Creating a new CancelEventArgs object has no side-effects that the plumbing can detect. 创建一个新的CancelEventArgs对象没有管道可以检测到的副作用。

There's something else wrong, events are raised for the benefit of external code, letting it know what's going on and giving it an option to alter behavior. 还有其他错误,为了外部代码的利益而提出事件,让它知道发生了什么,并给它一个改变行为的选项。 There is no external code here, the event handler is actually part of the same class that raises the event. 这里没有外部代码,事件处理程序实际上是引发事件的同一个类的一部分。 In other words, the form is listening to its own events. 换句话说,表单正在倾听自己的事件。 There's a much better way to deal with that, you override the method that raises the event. 有一个更好的方法来处理它,你覆盖引发事件的方法。 Like this: 像这样:

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

Now external code can override the default behavior, events are raised after the OnXxxx method runs. 现在,外部代码可以覆盖默认行为,在OnXxxx方法运行引发事件。 And you have a choice, if you do not want the external code to override the behavior, simply swap the two statements. 如果您不希望外部代码覆盖行为,您可以选择,只需交换这两个语句即可。

I think the code is doing exactly what it says; 我认为代码完全按照它的说法行事; what's missing is a literal reading of it. 缺少的是文字阅读。

When you assign a new value to e.Cancel , you are modifying the e that is provided as a parameter to the function. e.Cancel分配新值时,您正在修改作为函数参数提供的e After the event handler function finishes, this FormClosingEventArgs instance, including any changes made to it from within the event handler, will be available to whatever code invoked the event handler. 事件处理程序函数完成后,此FormClosingEventArgs实例(包括在事件处理程序中对其进行的任何更改)将可用于调用事件处理程序的任何代码。 In this case, that's almost certainly the Winforms code written by Microsoft. 在这种情况下,几乎可以肯定是Microsoft编写的Winforms代码。

On the flip side, when you inside that event handler create a new instance of the type FormClosingEventArgs and do something to it, there is nothing to provide that information back to the caller; 另一方面,当您该事件处理程序内部创建一个FormClosingEventArgs类型的新实例并对其执行某些操作时,没有任何内容可以将该信息提供给调用者; you'd need something explicit for that. 你需要一些明确的东西 Since the caller is looking at the value of the parameter it passed in once the event handler completes, you'd need to somehow replace the content of e as seen by the caller with the newly created instance. 由于调用者在事件处理程序完成后查看它传入的参数的值,因此您需要以某种方式用新创建的实例替换调用者看到的e的内容。 In other cases such a result might be provided as a return value. 在其他情况下,这样的结果可能作为返回值提供。

In general, the result of new T() , for some type T , is an instance of type T . 一般地,结果new T()对于一些类型T ,是类型的实例T You can thus work with the result of the expression new T() as you would a non-null variable of type T . 因此,您可以使用表达式new T()的结果,就像处理类型为T的非null变量一样。 In your particular case, you're assigning a value to a property on type T (specifically, the instance of that type thus created). 在您的特定情况下,您要为类型T上的属性赋值(具体而言,是由此创建的该类型的实例)。 (There is the special case where the constructor fails, but let's not go there for now; for simple types, that would pretty much mean that you are in such dire straits that your program is unlikely to be able to continue running in any case.) (有一种特殊情况,构造函数失败了,但是现在不要去那里;对于简单类型,这几乎意味着你处于如此困难的境地,以至于你的程序在任何情况下都不可能继续运行。 )

What's important here is that if you don't assign the result of the expression new T() itself anywhere, the newly created instance is thrown away (technically, becomes inaccessible) once the statement completes. 这里重要的是,如果你没有将表达式new T() 本身的结果分配到任何地方,那么一旦语句完成,新创建的实例就会被抛弃(技术上变得难以访问)。 Then at some later point, the .NET garbage collector kicks in and actually reclaims the memory that was allocated. 然后在稍后的某个时刻,.NET垃圾收集器启动并实际回收已分配的内存。 It isn't really any different from allocating a variable in one function, calling that function from another function and trying to access the variable thus allocated from the second function without doing anything to transfer the variable from the first function to the second, except here only one function is involved. 它与在一个函数中分配变量,从另一个函数调用该函数并尝试访问从第二个函数分配的变量并没有做任何事情来将变量从第一个函数传递到第二个函数实际上没有任何不同,除了这里只涉及一个功能。

Doing something like your second line of code in the event handler would be rather unusual, but can in principle be valid if invoking the constructor has some side effect that you're looking to make use of, such as triggering lazy loading. 在事件处理程序中执行类似第二行代码的操作会非常不寻常,但如果调用构造函数有一些副作用(例如触发延迟加载), 原则上可以有效。

This code surely work just check it 这段代码肯定只是检查它

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;
        }

Happy Coding 快乐的编码

It's because the CancelEventArgs is an object reference passed to the event handler in your code. 这是因为CancelEventArgs是一个传递给代码中事件处理程序的对象引用。 The behind the scenes code raises FormClosing with a CancelEventArgs object and all the event handlers receive that same object. 幕后代码使用CancelEventArgs对象引发FormClosing ,并且所有事件处理程序都接收相同的对象。 Once all the handlers have had their turn, the behind the scenes code checks the CancelEventArgs object it sent to see if its Cancel property is set to true . 一旦所有处理程序都轮到他们,后台代码就会检查它发送的CancelEventArgs对象,看看它的Cancel属性是否设置为true If it is, it doesn't do anything, and the FormClose chain of events stops. 如果是,则它不会执行任何操作,并且FormClose事件链将停止。 If Cancel is false ( CancelEventArgs default value), meaning it hasn't been set to Cancel the chain of events, the behind the scenes code proceeds along, and then raises the FormClosed event. 如果CancelfalseCancelEventArgs默认值),意味着它尚未设置为Cancel事件链,则幕后代码继续进行,然后引发FormClosed事件。

You can read more at Form.FormClosing Event on MSDN . 您可以在MSDN上的Form.FormClosing事件中阅读更多内容

In Forms all the -ing events are typically followed by an -ed event. Forms所有-ing事件通常后跟-ed事件。 The -ing events usually have CancelEventArgs , which can have its Cancel property set to true to stop the -ed event from happening. -ing事件通常具有CancelEventArgs ,可以将其Cancel属性设置为true以阻止-ed事件发生。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM