public static class ComponentHelper<T> where T : Control { public static bool HaveEventHandler(T control, string eventName, string methodName) { //获取Button类定义的所有事件的信息 PropertyInfo pi = (typeof(T)).GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic); //获取Button对象btn的事件处理程序列表 EventHandlerList ehl = (EventHandlerList)pi.GetValue(control, null); //获取Control类Click事件的字段信息 FieldInfo fieldInfo = (typeof(Control)).GetField($"Event{eventName}", BindingFlags.Static | BindingFlags.NonPublic); //用获取的Click事件的字段信息,去匹配btn对象的事件处理程序列表,获取btn对象Click事件的委托对象 //事件使用委托定义的,C#中的委托时多播委托,可以绑定多个事件处理程序,当事件发生时,这些事件处理程序被依次执行 //因此Delegate对象,有一个GetInvocationList方法,用来获取这个委托已经绑定的所有事件处理程序 Delegate d = ehl[fieldInfo.GetValue(null)]; foreach (Delegate del in d.GetInvocationList()) { //判断一下某个事件处理程序是否已经被绑定到Click事件上 Console.WriteLine(del.Method.Name == methodName); if (del.Method.Name == methodName) { return true; } } return false; } }
测试代码:
private void button1_Click(object sender, EventArgs e) { MessageBox.Show("Hello,button1_Click"); } private void button3_Click(object sender, EventArgs e) { this.Text += ComponentHelper<Button>.HaveEventHandler(this.button1, nameof(this.button1.Click), nameof(this.button1_Click)); this.Text += this.button1.HaveEventHandler(nameof(this.button1.Click), nameof(this.button1_Click)); }
改为给Control添加扩展方法。
/// <summary> /// 控件扩展类,判断某个事件已经绑定了某个事件处理程序 /// <para>Author:xyf</para> /// <para>Time : 2019/04/02 </para> /// <para>Email:qwergoodboy@qq.com</para> /// </summary> public static class ComponentHelper { public static bool HaveEventHandler(this Control control, string eventName, string methodName) { //获取Control类定义的所有事件的信息 PropertyInfo pi = (typeof(Control)).GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic); //获取Control对象control的事件处理程序列表 EventHandlerList ehl = (EventHandlerList)pi.GetValue(control, null); //获取Control类Click事件的字段信息 FieldInfo fieldInfo = (typeof(Control)).GetField($"Event{eventName}", BindingFlags.Static | BindingFlags.NonPublic); //用获取的Click事件的字段信息,去匹配btn对象的事件处理程序列表,获取control对象Click事件的委托对象 //事件使用委托定义的,C#中的委托时多播委托,可以绑定多个事件处理程序,当事件发生时,这些事件处理程序被依次执行 //因此Delegate对象,有一个GetInvocationList方法,用来获取这个委托已经绑定的所有事件处理程序 Delegate d = ehl[fieldInfo.GetValue(null)]; foreach (Delegate del in d.GetInvocationList()) { //判断一下某个事件处理程序是否已经被绑定到Click事件上 if (del.Method.Name == methodName) { return true; } } return false; } }
上述代码,起作用的根本原因在于Component 内有 受保护的字段Events ,该字段记录了附加到该控件的所有的事件处理函数。
而wpf 控件中没有该成员,所以无法使用该方法判断。但是可以使用UIElement类提供的 AddHandler 和 RemoveHandler方法。
参考链接:
https://bbs.csdn.net/topics/370003848
https://www.cnblogs.com/lujin49/archive/2012/02/23/2364185.html
https://blog.csdn.net/weixin_34090643/article/details/86311811