winform判断一个事件是否已经绑定了事件处理函数

 

 

  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

posted @ 2019-04-02 18:45  JeffreyGoogle  阅读(2613)  评论(0编辑  收藏  举报