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

https://blog.csdn.net/wyljz/article/details/49746549

winform判断一个事件是否已经绑定了事件处理函数的更多相关文章

  1. off() 方法 与 unbind() 方法移除绑定事件的处理程序。one()函数用于为每个匹配元素的一个或多个事件绑定一次性事件处理函数

    off() 方法移除用.on()绑定的事件处理程序. unbind() 方法移除用.bind()绑定的事件处理程序. 从 jQuery 1.7开始, .on() 和 .off()方法是最好的元素上附加 ...

  2. SQL判断一个事件段 是否在数据库中与其他时间段有重叠 判断时间重叠

    数据库字段startDate 开始时间   endDate 结束时间  -两个参数 比如查2-2  至2-6 在数据库中是否与其他时间有重叠 四个条件有一项满足则有重叠时间 思路是这样子 以开始和结束 ...

  3. Jquery中事件的重复绑定

    问题:事件的绑定具有叠加效果,已有绑定的函数时,再次绑定,执行时会出现绑定多少次,触发多少次的情况 解决:1.on();绑定事件,提供了绑定事件处理程序所需的所有功能,用于统一取代以前的bind(). ...

  4. java 判断一个字符串中的数字:是否为数字、是否包含数字、截取数字

    题外话: JavaScript中判断一个字符是否为数字,用函数:isDigit(); 一.判断一个字符串是否都为数字 package com.cmc.util; import java.util.re ...

  5. JavaScript移除绑定在元素上的匿名事件处理函数

    前言: 面试的时候有点蒙,结束之后想想自己好像根本就误解了面试官的问题,因为我理解的这个问题本身就没有意义.但是当时已经有一些思路,但是在一个点上被卡住. 结束之后脑子瞬间灵光,想出了当时没有迈出的那 ...

  6. jquery事件之事件处理函数

    一.事件处理 方法名 说明 语法 (events 事件类型,data数据,handler 事件处理函数,selector 选择器) Bind( 为每一个匹配元素的特定事件(像click)绑定一个事件处 ...

  7. JS绑定事件处理函数及处理流程

    一.事件绑定的几种方式: 1.1 ele.on+“事件名“:如div.onclick = function(event){ }; 1.1.1这种方式兼容性非常好,但一个元素的同一个事件上只能绑定一个处 ...

  8. winform 多个label绑定一个事件

    1当多个label帮到到一个事件后 private void jiandao_Click(object sender, EventArgs e) { //sender显示的是窗体上接受事件的label ...

  9. Javascript 事件对象(四)一个事件绑定多个不同的函数

    给一个对象绑定多个事件处理函数: <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-T ...

随机推荐

  1. __str__ 和 __repr

    #1 默认类里面默认提供的__str__方法,是返回类的内存地址class foo: def __init__(self): pass #2 修改类里面默认提供的__str__方法class fun: ...

  2. 编织织物的knit course direction and knit wale direction

    来自:http://www.definetextile.com/2013/04/course-wale.html

  3. virtual 函数只有在用指针或引用的方式访问,才会导致多态。

    只有用指针和引用,才会动态绑定.才会在运行时候从虚表中找对应的成员函数. 如果只是用.访问成员函数,是静态绑定,在编译时刻就固定好的. 另外,父类的虚函数,子类不管加不加virtual关键字,都是虚函 ...

  4. Hibernate 再接触 总结

  5. Hibernate 再接触 HQL

    Category.java package com.bjsxt.hibernate; import javax.persistence.Entity; import javax.persistence ...

  6. CSS表单2 组件排版

    <!DOCTYPE html> <html>     <head>         <title>单选按钮对齐</title>        ...

  7. js计算base64文件流大小

    getImgSize(str) { //获取base64图片大小,返回KB数字 var str = base64url.replace('data:image/jpeg;base64,', '');/ ...

  8. 通过windows远程桌面连接CentOS系统

    前提: CentOS安装桌面,如果无桌面,请执行 # yum -y groups install "GNOME Desktop" # startx 1 2 配置源 # yum in ...

  9. “AS3.0高级动画编程”学习:第四章 寻路(AStar/A星/A*)算法 (下)

    在前一部分的最后,我们给出了一个寻路的示例,在大多数情况下,运行还算良好,但是有一个小问题,如下图: 很明显,障碍物已经把路堵死了,但是小球仍然穿过对角线跑了出来! 问题在哪里:我们先回顾一下ASta ...

  10. vue 需求 data中的数据之间的调用

    我遇到过这种情况  就是在我的data中 会有数据调用data中的其他数据 如图  我的alertInfoType需要拿到screeningCondition中type的值 用过vue的都知道 我是不 ...