如何访问控件的事件?
我试图得到分配给控制的事件的名称例如:我有两个formsA和B. 表单B包含GridControl ,gridcontrol有一些事件,如gridControl1_Validating。
我的目标只是知道分配给控件的事件是什么
我的守则如下FOrm A.
public Control[] FilterControls(Control start, Func isMatch) { var matches = new List(); Action filter = null; (filter = new Action(c => { if (isMatch(c)) matches.Add(c); foreach (Control c2 in c.Controls) filter(c2); }))(start); return matches.ToArray(); } static void main[] { Control[] FoundControls = null; FoundControls = FilterControls(TF, c => c.Name != null && c.Name.StartsWith("grid")); var eventinfo = FoundControls[0].GetType().GetEvent("gridControl1.Validating", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); }
在编译时,我得到了我的控件,但我在eventinfo处于null,尽管gridcontrol事件在表单B中有此事件
请帮忙
尝试"Validating"
而不是"gridControl1.Validating"
“
var eventinfo = FoundControls[0].GetType().GetEvent( "Validating", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
虽然这与您已将事件处理程序附加到事件的事实无关。 您正在获取事件本身,而不是附加的处理程序。 您无法对eventInfo
变量执行任何有用的eventInfo
(除了添加和删除其他事件处理程序之外)。
要访问附加的处理程序(底层委托),您需要查看事件实现的代码(使用reflection器或dotPeek等反编译器 ,或使用Microsoft Reference Source ):
public event CancelEventHandler Validating { add { base.Events.AddHandler(EventValidating, value); } remove { base.Events.RemoveHandler(EventValidating, value); } }
事实certificate, Control
类使用名为Events
的EventHandlerList
类型的属性来存储基于键的所有委托(在本例中为EventValidating
字段)。
要检索事件的委托,我们应该从Events
属性中读取它们:
public static Delegate[] RetrieveControlEventHandlers(Control c, string eventName) { Type type = c.GetType(); FieldInfo eventKeyField = GetStaticNonPublicFieldInfo(type, "Event" + eventName); if (eventKeyField == null) { eventKeyField = GetStaticNonPublicFieldInfo(type, "EVENT_" + eventName.ToUpper()); if (eventKeyField == null) { // Not all events in the WinForms controls use this pattern. // Other methods can be used to search for the event handlers if required. return null; } } object eventKey = eventKeyField.GetValue(c); PropertyInfo pi = type.GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance); EventHandlerList list = (EventHandlerList)pi.GetValue(c, null); Delegate del = list[eventKey]; if (del == null) return null; return del.GetInvocationList(); } // Also searches up the inheritance hierarchy private static FieldInfo GetStaticNonPublicFieldInfo(Type type, string name) { FieldInfo fi; do { fi = type.GetField(name, BindingFlags.Static | BindingFlags.NonPublic); type = type.BaseType; } while (fi == null && type != null); return fi; }
和
public static List RetrieveAllAttachedEventHandlers(Control c) { List result = new List (); foreach (EventInfo ei in c.GetType().GetEvents()) { var handlers = RetrieveControlEventHandlers(c, ei.Name); if (handlers != null) // Does it have any attached handler? result.AddRange(handlers); } return result; }
最后一个方法将提取附加到控件事件的所有事件处理程序。 这包括来自所有类的处理程序(甚至由winforms内部附加)。 您还可以通过处理程序的目标对象筛选列表:
public static List RetrieveAllAttachedEventHandlersInObject(Control c, object handlerContainerObject) { return RetrieveAllAttachedEventHandlers(c).Where(d => d.Target == handlerContainerObject).ToList(); }
现在,您可以获取formB
定义的formB
所有事件处理程序:
RetrieveAllAttachedEventHandlersInObject(gridControl1, formB);