c# - 如何检查分配了哪个事件?

标签 c# winforms reflection controls

我的代码如下。

Control[] FoundControls = null;
FoundControls = MyFunctionToFilter(TF, c => c.Name != null && c.Name.StartsWith("grid"));
var eventinfo = FoundControls[0].GetType().GetEvents();

但是,eventinfo 为我提供了属于网格的所有控件的列表。 而在主类中只定义了两个事件,即 KeyDownValidating

如何获取这些分配事件的列表,即按键和验证?

最佳答案

Windows Forms (WinForms) 有一个复杂的组件事件模型(DataGridView 是一个组件)。一些事件继承自 Control(如 FontChangedForeColorChanged 等),但所有特定于组件的事件都存储在单个 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/

相关文章:

c# - UnobservedTaskException 没有终止进程

c# - Nest for elastic search 5.1 如何制作基本的 aggs?

c# - XML 序列化程序无法处理属性

c# - 如何将cmd命令输出放入标签中

WinForms TabControl 验证 : Switch to a tab where validation failed

c# - 我的 Winforms 编码方法是老派的吗

快速反射 : how to construct a new struct instance based on reflections?

c# - Visual Studio WinForms 设计器不实例化对象

php - PHP 中的模拟 exit() 函数

python - 为模块中的所有类覆盖 __init__