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. 2008nian元旦

    我要做---->> 控制财务状况---1记账 2 炒股或基金 3预算 锻炼---每次要达到锻炼的效果 学习计划-- 1报班架构 2 项目管理 3读书 爱好---做饭,收拾整理 职业规划. ...

  2. [C语言]进阶|指针与字符串

    ------------------------------------------------------------------------------------ 回顾:[C语言]指针与字符串 ...

  3. JSON转Excel

    1.引入js (dist目录下JsonExportExcel.min.js) <script src="https://cuikangjie.github.io/JsonExportE ...

  4. c# devexpress 多文档界面

    学习记录 https://blog.csdn.net/qq_25473787/article/details/81208894?utm_source=blogxgwz0

  5. 阿里巴巴Java开发手册与自己开发对照笔记

    一编程规约 (一)命名风格 某些时候在命名常量的时候,会觉得太长而减少长度导致命名不清. 抽象类及测试类写得比较少. 这一点值得注意,在开发中,布尔变量我都是使用is开始. 关于包名和类名的单数和复数 ...

  6. 【转】IO多路复用机制详解

    高性能IO模型浅析 服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(Blocking IO):即传统的IO模型. (2)同步非阻塞IO(Non-blocking  ...

  7. kalman滤波(二)---扩展kalman滤波[EKF]的推导

    一.状态估计的解释 我们知道每个方程都受噪声的影响,这里把位姿x和路标y看成服从某种概率分布的随机变量.因此我们关心的问题就变成了:当我们已知某些运动数据u和观测数据z时,如何确定状态量x,y的分布? ...

  8. 七、eclipse添加离线约束,使不联网也能有一些代码的提示,例如dubbo

    eclipse添加离线约束,使不联网也能有一些代码的提示,例如dubbo 1.将dubbo.xsd文件放到一个无中文目录下 2.eclipse->windows->preferences- ...

  9. 带标签的循环语句、switch

    今天继续更新,控制流程的剩余部分内容,带标签的循环语句中的continue/break 的使用方法,以及switch关键字的使用方法.例1:带标签的continue/break.package com ...

  10. MySQL数据查询之单表查询

    单表查询 简单查询 - 创建表 DROP TABLE IF EXISTS `person`; CREATE TABLE `person` ( `id` ) NOT NULL AUTO_INCREMEN ...