Windows 窗体(WinForms) 有一个复杂的组件事件模型(并且DataGridView
是一个组件)。一些事件继承自Control
(如FontChanged
,ForeColorChanged
等),但所有特定于组件的事件都存储在单个EventHandlerList对象中,该对象继承自Component
(顺便说一句,来自 Control 的事件也存储在那里,请参阅末尾的更新)回答)。有一个受保护的Events
财产:
protected EventHandlerList Events
{
get
{
if (this.events == null)
this.events = new EventHandlerList(this);
return this.events;
}
}
以下是为事件添加事件处理程序的方式DataGridView
:
public event DataGridViewCellEventHandler CellValueChanged
{
add { Events.AddHandler(EVENT_DATAGRIDVIEWCELLVALUECHANGED, value); }
remove { Events.RemoveHandler(EVENT_DATAGRIDVIEWCELLVALUECHANGED, value); }
}
如您所见,委托(值)通过EventHandlerList
一些键值传递给。所有事件处理程序都按键存储在那里。您可以将EventHandlerList
其视为一个字典,其中对象作为键,委托作为值。所以,这里是如何通过反射获取组件的事件。第一步是获取这些密钥。正如您已经注意到的,它们被命名为EVENT_XXX
:
private static readonly object EVENT_DATAGRIDVIEWCELLVALUECHANGED;
private static readonly object EVENT_DATAGRIDVIEWCELLMOUSEUP;
// etc.
所以我们开始:
var keys = typeof(DataGridView) // You can use `GetType()` of component object.
.GetFields(BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy)
.Where(f => f.Name.StartsWith("EVENT_"));
接下来,我们需要我们的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;
最后一步,获取附加了处理程序的键列表:
var result = keys.Where(f => handlers[f.GetValue(null)] != null)
.ToList();
那会给你钥匙。如果您需要委托,那么只需在处理程序列表中查找它们。
更新:继承自Control
的事件也存储在 中EventHandlerList
,但由于某些未知原因,它们的键具有不同的名称,例如EventForeColor
. 您可以使用与上述相同的方法来获取这些密钥并检查是否附加了处理程序。