C# – Intercepting and cancelling the Click event of a WinForms Button

ccompact-frameworkeventswinforms

Is there a way to capture the Click event of a Button from the parent Control and prevent it occuring if a variable within the parent Control is true?

For example:

private void AssignEventOverrides()
{
    foreach (Button button in Buttons) 
    {
        // Get the event assigned at design time
        var someUnknownEventHandler = GetTheClickHandlerSomehow(button);

        // Unsubscribe the unknown event
        button.Click -= SomeUnknownEventHandler;

        // Assign the intercepting event
        button.Click += button_Click;
    }
}

private void button_Click(object sender, EventArgs e)
{
    if (!preventClick)
    {
        // Fire the intercepted event that was previously unsubscribed
    }
}

Hopefully there's a nicer way to do this than the above example. Just to note, I don't have any control over the events assigned to the afforementioned buttons. They're subscribed elsewhere and I just need to prevent them happening if a variable is true on the consuming parent Control.

My real scenario:

I'm using Windows Mobile 6.5 (legacy application rewrite) I've created a panel control that can contain N number of child controls. The panel control allows for iPhone style vertical scrolling. I subscribe to the MouseMove event of the child Control and set a variable _isScrolling to true. In the MouseUp event I set _isScrolling to false.

As Click occurs before MouseUp I can check within the Click event to ensure a scroll hadn't occured when the button was pressed. So basically, if a scroll of my panel occurs, I need to prevent the Click event (subscribed at design time) from firing.

Best Answer

This might provide some useful insight

How to remove all event handlers from a control

Specifically, look at

private void RemoveClickEvent(Button b)
{
    FieldInfo f1 = typeof(Control).GetField("EventClick", 
        BindingFlags.Static | BindingFlags.NonPublic);
    object obj = f1.GetValue(b);
    PropertyInfo pi = b.GetType().GetProperty("Events",  
        BindingFlags.NonPublic | BindingFlags.Instance);
    EventHandlerList list = (EventHandlerList)pi.GetValue(b, null);
    list.RemoveHandler(obj, list[obj]);
}