How to subscribe to any event in the control dynamically in C #

Source: Internet
Author: User

I thought about this question for a long time and it is not easy to describe it in one sentence. In this way, a simple application scenario is as follows: using the Windows Forms production wizardProgramUsually there are buttons such as "previous" and "Next. Assume that you need to create a general "Wizard Production Framework", then we need to make the framework in this "Wizard Production Framework, controls whether the buttons "previous" and "Next" are available (Enabled or not. The control conditions are determined by developers when they actually use the "Wizard creation framework" for development. For example, "Next" is available only after a string is entered in a text box on the current Wizard Page, or "Next" is available only when a button is pressed. Therefore, our "Wizard creation framework" must be able to allow developers to determine what to trigger before "Next" is available.

 

Let's start with a special case. Suppose there is only one button on the Wizard Page called BTN. Only after you click BTN can you click "Next. This effect can be easily achieved through programming: the BTN click event is subscribed directly on the form, and the "btnnext. Enabled = true;" statement is written in the click event.

 

Now the problem arises: we need to provide developers with a "wizard production framework". That is to say, this framework cannot predict which controls the developers need to subscribe to and which events can only set aside one interface, developers can call this interface to dynamically register events. Windows Forms provides various types of controls, and different events have different function signatures (that is, the delegate, such as the Click Event and the mousedown event use two different commissions ), how to enable our framework to support any controls and call "btnnext. enabled = true; "This statement makes the" Next "button available?

 

Reflection is required to implement such a function. First, define a generic method. In this method, we directly set btnnext as follows:

 

View Source

Print?

1 Protected Void Dotrigger <t> (Object Sender, t eventargs)
2 Where T: system. eventargs
3 {
4 This. Btnnext. Enabled =True;
5 }

Then, the eventinfo object is obtained based on the control instance and event name given by the user. An important attribute in eventinfo is eventhandlertype, which defines the delegate type used by the event. To bind events specified by developers to the preceding dotrigger function, we need to know the specific eventargs type.CodeYou can read all the parameter types of a delegate type:

 

 

View Source

Print?

01 Private Type [] getdelegateparametertypes (type D)
02 {
03 If (D. basetype! =Typeof(Multicastdelegate ))
04 {
05 Throw New Invalidoperationexception ("Not a delegate .");
06 }
07  
08 Methodinfo invoke = D. getmethod ("INVOKE");
09 If (Invoke =Null)
10 {
11 Throw New Invalidoperationexception ("Not a delegate .");
12 }
13  
14 Parameterinfo [] parameters = invoke. getparameters ();
15 Type [] typeparameters =New Type [parameters. Length];
16 For (Int I = 0; I <parameters. length; I ++)
17 {
18 Typeparameters [I] = parameters [I]. parametertype;
19 }
20  
21 Return Typeparameters;
22 }

 

Note: For standard event delegation, generally the first parameter is of the object type, the second parameter is of the eventargs binding type, and the signature format with no return value is used. In other words, in general, the array returned by the above Code contains two objects: object and a type that inherits from eventargs (or eventargs itself. Here, we take the second member in the array.

Now, through reflection, get the methodinfo of dotrigger method, bind the eventargs type obtained in the previous step to the dotrigger method, and use delegate. createdelegate to generate event handler:

View Source

Print?

01 Private Delegate geteventhandler (Control, 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 }

You can obtain the event handler that processes the event by passing in the method info of any control and any event in the control, that is, the dotrigger generic method is used to process the specified event:

View Source

Print?

01 Public Void Registertrigger (Control,String Eventname)
02 {
03 Try
04 {
05 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 }

Finally, the Code is easy to use:

View Source

Print?

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 }

Now, whether the BTN is clicked, the text in textbox1 is changed, or the textbox2 mouse button is pressed, The dotrigger function is directly triggered, the "Next" button becomes available (enabled is true ).

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.