我的代码如下。
Control[] FoundControls = null;
FoundControls = MyFunctionToFilter(TF, c => c.Name != null && c.Name.StartsWith("grid"));
var eventinfo = FoundControls[0].GetType().GetEvents();
但是,eventinfo 为我提供了属于网格的所有控件的列表。 而在主类中只定义了两个事件,即 KeyDown 和 Validating。
如何获取这些分配事件的列表,即按键和验证?
最佳答案
Windows Forms (WinForms) 有一个复杂的组件事件模型(DataGridView
是一个组件)。一些事件继承自 Control
(如 FontChanged
、ForeColorChanged
等),但所有特定于组件的事件都存储在单个 EventHandlerList 对象中,它继承自 Component
(顺便说一句,来自 Control 的事件也存储在那里,请参阅答案末尾的更新)。有一个 protected 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); }
}
如您所见,delegate (value) 被传递给带有一些键值的 EventHandlerList
。所有事件处理程序都按键存储在那里。您可以将 EventHandlerList
视为字典,其中对象为键,委托(delegate)为值。因此,这里是如何通过反射获取组件的事件。第一步是获取这些 key 。正如您已经注意到的,它们被命名为 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();
这会给你 key 。如果您需要委托(delegate),只需在处理程序列表中查找它们即可。
更新:从 Control
继承的事件也存储在 EventHandlerList
中,但由于某些未知原因,它们的键具有不同的名称,例如 EventForeColor
.您可以使用与上述相同的方法来获取这些 key 并检查是否附加了处理程序。
关于c# - 如何检查分配了哪个事件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15630943/