Thursday, January 04, 2007

There is a very useful class in the .NET framework that allows you to cancel an event from the handler perspective. This class is the CancelEventArgs. Typically using this class looks as follows:

event EventHandler<CancelEventArgs> Click;
void OnClick()
{
    CancelEventArgs e = new CancelEventArgs();
    Click(this, e);
    if (e.Cancel)
    {
        // do nothing
    }
    else
    {
        // do something
    }
}

void ClickHandler(object sender, CancelEventArgs e)
{
    if (something)
    {
        e.Cancel = true;
    }
}

BTW: I have no idea why Microsoft defined CancelEventArgs under System.ComponentModel namespace.

Simple and easy. But there is a problem. What if there was a second handler for the Click event?

void ClickHandler2(object sender, CancelEventArgs e)
{
    e.Cancel = !IsValid();
}

In some scenarios, the ClickHandler2 would override changes made by ClickHandler - i.e. it would set Cancel property to false in case the state was Valid. I strongly discourage you from ever setting Cancel property to false! The problem is that in the handler method you never know if you are the only one handler or are there more handlers involved! If a previous handler had already cancelled the event you will lose this information!

In order to prevent potential mistakes, I propose an alternative version of CancelEventArgs. The version that will prevent you from making a mistake. Below is a how such a class could look like:

class CancelEventArgs : EventArgs
{
    bool cancelled;
    public bool Cancelled
    {
        get { return cancelled; }
    }
    public void Cancel()
    {
        cancelled = true;
    }
}

Notice that the Cancel property is now called Cancelled and is read-only. To Cancel an event you use the Cancel method which works only one way - there is no way to accidentally set Cancelled to false. The safer, the better :-)

kick it on DotNetKicks.com