C#中动态订阅控件中任意事件的方法
2010-09-30 22:42:48 来源:WEB开发网注意:如果是标准的事件委托,一般情况下都是第一个参数为object类型,第二个参数为EventArgs绑定类型,无返回值的签名格式。换句话说,一般情况下,上面的这段代码返回的数组包含两个对象:object和一个继承于EventArgs(或者是EventArgs本身)的类型。在这里,我们取数组里的第二个成员。
好了,现在通过反射,获得DoTrigger方法的MethodInfo,并通过MethodInfo.MakeGenericMethod方法,将上一步获得的EventArgs类型绑定到DoTrigger方法上,并使用Delegate.CreateDelegate生成Event Handler:
01 private Delegate GetEventHandler(Control control, EventInfo eventInfo)
02 {
03 try
04 {
05 if (eventInfo == null)
06 throw new Exception(string.Format("Unable to find an event named '{0}' on the control '{1}'.",
07 eventInfo.Name, control));
08 Type[] delegateParameters = this.GetDelegateParameterTypes(eventInfo.EventHandlerType);
09 if (delegateParameters == null ||
10 delegateParameters.Length != 2)
11 throw new InvalidOperationException(string.Format("Event '{0}' is not valid.", eventInfo.Name));
12 Type eventArgsType = delegateParameters[1];
13
14 MethodInfo doEventMethod = this.GetType().GetMethod("DoTrigger",
15 BindingFlags.NonPublic | BindingFlags.Instance);
16
17 if (doEventMethod == null)
18 throw new Exception("DoTrigger method doesn't exist.");
19 if (!doEventMethod.IsGenericMethod)
20 throw new Exception("DoTrigger method is not a generic method.");
21 MethodInfo concreteDoEventMethod = doEventMethod.MakeGenericMethod(eventArgsType);
22 Delegate d = Delegate.CreateDelegate(eventInfo.EventHandlerType, this, concreteDoEventMethod);
23 return d;
24 }
25 catch
26 {
27 throw;
28 }
29 }
通过向上面的方法传入一个任意控件和该控件中任意事件的Method Info,即可获得处理该事件的Event Handler,也就是由DoTrigger泛型方法来处理该指定的事件:
01 public void RegisterTrigger(Control control, string eventName)
02 {
03 try
04 {
05 EventInfo eventInfo = control.GetType().GetEvent(eventName,
06 BindingFlags.Public | BindingFlags.Instance);
07
08 Delegate d = this.GetEventHandler(control, eventInfo);
09 eventInfo.AddEventHandler(control, d);
10 }
11 catch
12 {
13 throw;
14 }
15 }
最后,在使用的时候,代码就简单啦:
1 private void Form_Load (object sender, System.EventArgs e)
2 {
3 this.RegisterTrigger (btn, "Click");
4 this.RegisterTrigger (textBox1, "TextChanged");
5 this.RegisterTrigger (textBox2, "MouseDown");
6 }
现在,不管是btn被单击,还是textBox1里的文字被更改,还是在textBox2鼠标按钮被按下,都会直接触发DoTrigger函数,进而使得“下一步”按钮变得可用(Enabled为true)。
更多精彩
赞助商链接