"e.Cancel " in formclosing Event
Asked Answered
M

4

11

When using the FormClosing event, why does the code e.Cancel = true; work, but new CancelEventArgs().Cancel = true; does not work?

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

    new CancelEventArgs().Cancel = true;
}
Magocsi answered 28/2, 2011 at 13:21 Comment(0)
C
23

The event is raised by the Winforms plumbing code. The only way it can see that the custom event handler wants to alter the default behavior is through the e object. Creating a new CancelEventArgs object has no side-effects that the plumbing can detect.

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. And you have a choice, if you do not want the external code to override the behavior, simply swap the two statements.

Carioca answered 28/2, 2011 at 13:55 Comment(0)
M
15

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. 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. In this case, that's almost certainly the Winforms code written by Microsoft.

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; 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. 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. You can thus work with the result of the expression new T() as you would a non-null variable of type T. In your particular case, you're assigning a value to a property on type T (specifically, the instance of that type thus created). (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. Then at some later point, the .NET garbage collector kicks in and actually reclaims the memory that was allocated. 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.

Maeve answered 28/2, 2011 at 13:24 Comment(0)
E
6

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

Encircle answered 21/2, 2013 at 7:54 Comment(0)
N
3

It's because the CancelEventArgs is an object reference passed to the event handler in your code. The behind the scenes code raises FormClosing with a CancelEventArgs object and all the event handlers receive that same object. 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. If it is, it doesn't do anything, and the FormClose chain of events stops. 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.

You can read more at Form.FormClosing Event on MSDN.

In Forms all the -ing events are typically followed by an -ed event. The -ing events usually have CancelEventArgs, which can have its Cancel property set to true to stop the -ed event from happening.

Nalda answered 3/5, 2013 at 17:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.