Windows Forms (WinForms) has a tricky model of events for components (and DataGridView
is a component). Some events are inherited from Control
(like FontChanged
, ForeColorChanged
, etc.), but all specific to component events are stored in a single EventHandlerList object, which is inherited from Component
(BTW, events from Control are also stored there, see the update at the end of the answer). There is a protected Events
property for that:
protected EventHandlerList Events
{
get
{
if (this.events == null)
this.events = new EventHandlerList(this);
return this.events;
}
}
And here is the way how event handlers are added for DataGridView
events:
public event DataGridViewCellEventHandler CellValueChanged
{
add { Events.AddHandler(EVENT_DATAGRIDVIEWCELLVALUECHANGED, value); }
remove { Events.RemoveHandler(EVENT_DATAGRIDVIEWCELLVALUECHANGED, value); }
}
As you can see, delegate (value) is passed to EventHandlerList
with some key value. All event handlers are stored there by key. You can think about EventHandlerList
as a dictionary with objects as keys, and delegates as values. So, here is how you can get components' events with reflection. The first step is getting those keys. As you already noticed, they are named as EVENT_XXX
:
private static readonly object EVENT_DATAGRIDVIEWCELLVALUECHANGED;
private static readonly object EVENT_DATAGRIDVIEWCELLMOUSEUP;
// etc.
So here we go:
var keys = typeof(DataGridView) // You can use `GetType()` of component object.
.GetFields(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy)
.Where(f => f.Name.StartsWith("EVENT_"));
Next, we need our EventHandlerList
:
var events = typeof(DataGridView) // or GetType()
.GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic);
// Could be null, check that
EventHandlerList handlers = events.GetValue(grid) as EventHandlerList;
And the last step, getting the list of keys, which have handlers attached:
var result = keys.Where(f => handlers[f.GetValue(null)] != null)
.ToList();
That will give you the keys. If you need delegates, then simply look in the handlers list for them.
UPDATE: Events which inherited from Control
are also stored in EventHandlerList
, but for some unknown reason their keys have different names, like EventForeColor
. You can use the same approach as above to get those keys and check if handlers are attached.