是否有可能"偷"从一个控件的事件处理程序,并把它交给别人呢。 [英] Is it possible to "steal" an event handler from one control and give it to another?

查看:128
本文介绍了是否有可能"偷"从一个控件的事件处理程序,并把它交给别人呢。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要做的是这样的:

 按钮BTN1 =新按钮();
btn1.Click + =新的EventHandler(btn1_Click);
按钮BTN2 =新按钮();
//采取任何事件得到了分配给BTN1并指定为BTN2。
btn2.Click + = btn1.Click; //编译器说,没有...
 

在哪里btn1_Click已经在类中定义的:

 无效btn1_Click(对象发件人,EventArgs的)
{
    //
}
 

(事件System.Windows.Forms.Control.Click只能出现在左边+ =或 - =)

这将无法编译,当然。有没有办法把事件处理程序从一个控件,并将其分配到另一个在运行时?如果这是不可能的,是重复的事件处理程序,并把它分配给另一个控件在运行时是可行的?

这几点:我用Google搜索的挫折感了这一一段时间,发现没有办法做这些事的。大多数试图办法涉及的反射,所以如果你看过我的问题,并认为答案是非常明显的,请尽量先编译code在Visual Studio。或者,如果答案真的是令人难以置信的明显,请随时打我吧。谢谢,我真的很期待看到这是可能的。

我知道我可以做到这一点:

  btn2.Click + =新的EventHandler(btn1_Click);
 

这不是我要找的位置。

这也不是什么我要找:

 事件处理程序得心应手=新的EventHandler(btn1_Click);
按钮BTN1 =新按钮();
btn1.Click + =得心应手;
按钮BTN2 =新按钮();
btn2.Click + =得心应手;
 

解决方案

是的,这在技术上是可行的。反思是必要的,因为有许多成员都是私有的和内部的。启动一个新的 Windows窗体项目,并添加两个按钮。然后:

 使用系统;
使用System.ComponentModel;
使用System.Windows.Forms的;
使用的System.Reflection;

命名空间WindowsFormsApplication1 {
  公共部分Form1类:表格{
    公共Form1中(){
      的InitializeComponent();
      button1.Click + =新的事件处理程序(的button1_Click);
      //获取秘密click事件的关键
      字段信息eventClick = typeof运算(控制).GetField(EventClick,BindingFlags.NonPublic可| BindingFlags.Static);
      反对秘密= eventClick.GetValue(空);
      //获得的点击事件
      的PropertyInfo eventsProp = typeof运算(组件).GetProperty(事件,BindingFlags.NonPublic可| BindingFlags.Instance);
      EventHandlerList事件=(EventHandlerList)eventsProp.GetValue(按钮1,NULL);
      代表点击=事件[密]
      //从Button1的删除它,把它添加到BUTTON2
      events.RemoveHandler(秘密,点击)
      事件=(EventHandlerList)eventsProp.GetValue(按钮2,NULL);
      events.AddHandler(秘密,点击)
    }

    无效的button1_Click(对象发件人,EventArgs的){
      的MessageBox.show(亚达);
    }
  }
}
 

如果这会让你确信微软试图真的很难prevent您从做这个,你明白了code。

What I want to do is something like this:

Button btn1 = new Button();
btn1.Click += new EventHandler(btn1_Click);
Button btn2 = new Button();
// Take whatever event got assigned to btn1 and assign it to btn2.
btn2.Click += btn1.Click; // The compiler says no...

Where btn1_Click is already defined in the class:

void btn1_Click(object sender, EventArgs e)
{
    //
}

This won't compile, of course ("The event 'System.Windows.Forms.Control.Click' can only appear on the left hand side of += or -="). Is there a way to take the event handler from one control and assign it to another at runtime? If that's not possible, is duplicating the event handler and assigning it to another control at runtime doable?

A couple of points: I have googled the heck out of this one for awhile and found no way of doing it yet. Most of the attempted approaches involve reflection, so if you read my question and think the answer is incredibly obvious, please try to compile the code in Visual Studio first. Or if the answer really is incredibly obvious, please feel free to slap me with it. Thanks, I'm really looking forward to seeing if this is possible.

I know I could just do this:

btn2.Click += new EventHandler(btn1_Click);

That's not what I'm looking for here.

This is also not what I'm looking for:

EventHandler handy = new EventHandler(btn1_Click);
Button btn1 = new Button();
btn1.Click += handy;
Button btn2 = new Button();
btn2.Click += handy;

解决方案

Yeah, it's technically possible. Reflection is required because many of the members are private and internal. Start a new Windows Forms project and add two buttons. Then:

using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Reflection;

namespace WindowsFormsApplication1 {
  public partial class Form1 : Form {
    public Form1() {
      InitializeComponent();
      button1.Click += new EventHandler(button1_Click);
      // Get secret click event key
      FieldInfo eventClick = typeof(Control).GetField("EventClick", BindingFlags.NonPublic | BindingFlags.Static);
      object secret = eventClick.GetValue(null);
      // Retrieve the click event
      PropertyInfo eventsProp = typeof(Component).GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);
      EventHandlerList events = (EventHandlerList)eventsProp.GetValue(button1, null);
      Delegate click = events[secret];
      // Remove it from button1, add it to button2
      events.RemoveHandler(secret, click);
      events = (EventHandlerList)eventsProp.GetValue(button2, null);
      events.AddHandler(secret, click);
    }

    void button1_Click(object sender, EventArgs e) {
      MessageBox.Show("Yada");
    }
  }
}

If this convinces you that Microsoft tried really hard to prevent your from doing this, you understood the code.

这篇关于是否有可能"偷"从一个控件的事件处理程序,并把它交给别人呢。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆