Current location - Quotes Website - Signature design - Find an example of C# event handling.
Find an example of C# event handling.
6.2 custom events

Custom events are a typical application of delegation! When developers write WinForm or ASP.NET applications, they will use Button's Click event. So, how is this event connection mechanism realized? Can we write our own defined events? In addition, when do we need to write our own defined events?

6.2. 1 Why use custom events?

Many developers will ask the author this question-"Why write your own events? There are many events integrated in the control. Isn't that enough for us? " .

In the implementation, if you don't know how to write custom events, it will be difficult to launch a truly usable application. The main reasons are as follows:

1. Custom control

Usually, in order to reduce the amount of repetitive interface function code, developers often develop some user controls or custom controls. At this time, we will have problems. The control provided by Microsoft contains many events, so will the control we write ourselves have many events?

2. Self-written components and class libraries

Events are not limited to control classes in the UI layer. Many basic classes also contain events, such as the SqlConnection class. The class view of this class is as follows:

The InfoMessage event is contained in this class and used to "occur when SQL Server returns a warning or informational message". In other words, when we write a class ourselves, a special data transmission situation often happens, that is, the direction of data transmission is from bottom to top. To explain this "bottom-up" delivery model, let's first look at an application hierarchy diagram:

The above picture is a three-layer architecture diagram of a conventional Socket communication software. The interface between the client and the server is two "EXE" programs, but in order to better manage the system logic, we usually package all the communication logic into two "DLL" files at the business logic layer. The arrow direction in the figure is the realization of the whole system function, which is realized by calling the bottom "DLL" from the "EXE" of the interface.

However, all communication functions are implemented in classes defined in DLL. Then, when the client's DLL sends a message to the server's DLL and is intercepted by the server's DLL, how does the "EXE" of the server interface know? Have we ever thought about this problem when we usually use QQ and MSN?

At this time, the problem we just mentioned appears again-"bottom-up", that is, the class in the lower "DLL" informs the interface in the upper "EXE". You can't call EXE with DLL anymore!

Note: Usually. NET platform can reference EXE, but as shown above, EXE has already referenced DLL, and IDE will no longer allow DLL to reference EXE to prevent deadlock caused by circular reference. Even if the IDE allows us to reference EXE with DLL, the instance created after the reference and the instance of the currently running interface are located in different memories, so any operation will not take effect.

At this point, we can use the event mechanism implemented by the delegate to solve the problem!

Events in control

To understand the event mechanism, let's start with the events in the control. Let's take Button's Click event as an example to illustrate.

When the developer double-clicks the button, the IDE will turn the designer to the code view and generate an event callback method for us, as shown in the following figure:

Note: button 1_Click here is not an event, but a method called when the event occurs!

Our question is, why is the button 1 _ Click method called after the click event of the button1? In fact, when we double-click Button 1, the IDE will automatically add a piece of code, which is located in "Form 1". Designer.cs "(Form 1.1excludes form1. Designer.cs), "Form 65438+"

Open the form 1. Designer.cs, expand the "InitializeComponent ()" method to find the 42nd line, as shown in the following figure:

We can see the following code:

this.button 1。 Click+= new system. EventHandler(this . button 1 _ Click);

In fact, this code is called the event registration code. This code means: If the Click event of this.button 1 occurs, go to this. Button 1_Click method for processing.

In order to better understand the event registration process, we first modify the 42nd line of code, as shown in the following figure:

Here, we will put the original

this.button 1。 Click+= new system. EventHandler(this . button 1 _ Click);

be revised as

this.button 1。 Click = New System. EventHandler(this . button 1 _ Click);

In this program, the modification here is for better understanding, of course, this writing is grammatically wrong.

Let's analyze it below:

First, observe the expression to the right of "=".

New system. EventHandler(this . button 1 _ Click);

Through the explanation of section 6. 1. 1, we can find that this code actually creates an instance of the delegate type and makes the delegate point to the this.button 1_Click method. That is to say, at "a certain moment" when the program is running, the system will indirectly call this.button 1_Click method through this delegate instance.

Then, let's observe the expression to the left of "=". In C-style language, "=" is an assignment expression, that is, the data types of the expressions on both sides of "=" should be the same. Therefore, because the expression to the right of "=" is an instance of the delegate type (system. EventHandler),this.button 1。 Click should also be a delegate type (system. EventHandler)。

Through the above explanation, we get a message that the event registration code in the previous paragraph makes this.button 1. Click and system.eventhandler (this.button1_ click) point to the same memory space. Simply put, it is this.button 1. Click points to this.button 1_Click method and calls this.button 1. Click is equivalent to calling this.button 1_Click method. So we say that when the Click event of this.button 1 occurs, the method of this.button 1_Click will be called.

When the program is running, the system will check whether this button 1 has been clicked. If it is clicked, it will call button 1. Click the internal button 1. At this point, the button 1_Click method in the Windows window will be executed.

Of course, the activity registration code can be completely handwritten. Because, except the event registration code in the control is automatically generated, the event registration in other classes is handwritten. The method of manually registering an event is as follows:

First, you can add an event to any code before it happens (usually in the window constructor). Let's register the MouseMove event of button 1 manually, as shown in the following figure:

When we finish writing "=", the prompt "Press TAB to Insert" will appear. At this point, we only need to press the "TAB" key twice, and the event registration and the method for callback will be added to the code window, as shown in the following figure:

The automatically generated code points the MouseMove event of this.button 1 to the button 1_MouseMove method. This handwritten code is exactly the same as the code automatically generated by IDE.

Of course, as a control event, we can automatically generate it. If you want to automatically generate other events of button 1, just look at the property window of button 1 and click the button to open the event list of this control, as shown in the following figure:

Then double-click the event you want and the code will be generated automatically.

In the previous code, in order to better understand event registration, we used to

this.button 1。 Click+= new system. EventHandler(this . button 1 _ Click);

be revised as

this.button 1。 Click = New System. EventHandler(this . button 1 _ Click);

We will find that both the self-written event registration code and the automatically generated code are implemented with "+=". In fact, as an event registration code, we can only use "+=" to achieve registration. Simply using "=" is grammatically wrong! ! !

The "+=" operator is a common operator in C-style languages, such as

int I = 0;

I+= 1;

same as

int I = 0;

I = I+ 1;

Therefore,

this.button 1。 Click+= new system. EventHandler(this . button 1 _ Click);

In principle, equivalent to

this.button 1。 Click = this.button 1. Click+

New system. EventHandler(this . button 1 _ Click);

Using natural language to describe the above code is "a delegate = this delegate itself+another delegate". So what does it mean to add a delegate?

6. 1.3 We discussed multicast delegation. The event itself is a delegation, and all delegations are derived from the system. In section 6. 1.3, we have demonstrated that adding multiple delegate types means that these delegate instances are stored in the call chain of multicast delegates. When a multicast delegate is called, the multicast delegate

Using the principle of multicast delegation, we can register multiple methods with an event, as follows:

this.button 1。 Click+= new system. EventHandler(this . button 1 _ Click);

this.button 1。 Click+= new system. EventHandler(this . button 1 _ click 1);

this.button 1。 Click+= new system. EventHandler(this . button 1 _ click 2);

The above code registers three methods in the Click event of button 1. When the Click event of button 1 is triggered, the button 1_Click, button 1_Click and button 1_Click2 methods will be called in turn. The advantage of this is that we can put multiple functions and operations with completely independent logic in different methods. When the event occurs, these methods will be called to realize the cascade operation I need.

6.2.3 Callback method of events in control

After the event registration, let's talk about the callback method of the event. First, we must review the code of event registration again:

this.button 1。 Click+= new system. EventHandler(this . button 1 _ Click);

In the above code, an instance of a system. EventHandler delegate type is a method that points to this.button 1_Click by using "new system". Eventhandler (this。 Button 1 _ click) ". From the contents mentioned in section 6. 1. 1, we know that if you want a delegate to point to a method, then the delegate and the pointed method must have the same signature (with the same parameter list and the same return value). Therefore, the system. The EventHandler type and this.button 1_Click method have the same signature. Let's see what the signature of the system is. The EventHandler delegate looks like:

Public delegate void EventHandler (

Object sender,

EventArgs e

)

Signature of the system. EventHandler is: the return value is void and there are two parameters, objectsender and eventargse. So the button 1_Click method has the same form, and the code is as follows:

Private void button 1_Click (object sender, EventArgs e)

{

}

In fact, the signatures of the event callback methods we can see are basically few, but the second parameter is slightly different. Next, we will explain the parameters of this method.

Object sender

The function of this parameter can be seen from its naming. The sender means that the person who triggered this event is the sender. Because theoretically all types can contain events, the sender's type is defined as the object type. When multiple events point to an event callback method at the same time, it can be used to distinguish which class triggered the event, so as to make different treatments. At this point, the parameter sender needs to be processed.

Case operation 020603: Multiple events point to the same callback method.

First, add three buttons and a text box.

The interface is as follows:

Then, add a method ButtonClick in the main window, which will be called by the Click events of these three buttons.

The code is as follows:

Protected void ButtonClick (object sender, EventArgs e)

{

Button bt = sender as button;

This.textBox 1。 Text = "I am:" +bt. Text;

}

In the above code, in order to know which Button was clicked, we converted sender to button type.

Let's specify the Click event callback method of these three buttons.

First, switch to the property window (F4) of button 1, Click the ""button, find the "click" event, and set the calling method to ButtonClick, as shown in the following figure.

Then, the Click events of button2 and button3 are set in the same way, all pointing to the ButtonClick method.

Finally, run the program, and the following is the running situation:

Click the button 1:

Click button 2:

Click button 3:

EventArgs e

The EventArgs type is an event parameter through which some data can be passed when an event occurs. Of course, the EventArgs class itself cannot pass any data. The class view of this class is as follows:

Judging from the class, it is not difficult to find that there are few members in this class. Usually, if you want to pass data, the event parameter class will generally be a derived class of the EventArgs class. For example, the event parameter in the KeyDown event of the TextBox class is a parameter of type KeyEventArgs, and the prototype of the event callback method is as follows:

Private void textBox 1_KeyDown (object sender, KeyEventArgs e)

{

}

The class view of KeyEventArgs class is as follows:

This class has three properties: "Alt", "Control" and "Shift", which are used to indicate whether the three function keys are pressed while pressing a key of the keyboard.

In addition, the "KeyCode" property can be used to indicate the name of the key pressed by the current user.

In the next section, we will explain how to write custom event parameters.

Case operation 020604: Use the KeyDown event of TextBox to simulate QQ chat window.

Create a new Windows window, including the following controls

RichTextBox control (rtbMessage): used to display chat information.

A text box control (tbxInput): used to enter chat information.

A button control (btSubmit): used to submit

The interface is as follows:

These functions are as follows:

Click the button to send the message to the RichTextBox above. Of course, if you press "Ctrl+Enter", you can also pass the text into RichTextBox.

First, we add a method in the Windows window with the following code:

Public empty display ()

{

this . rtb message . appendtext(this . tbx input。 text+" n ");

this . tbx input . text = " ";

}

The function of this method is to add the text in the text box to the RichTextBox.

Next, write the button Click event, the code is as follows:

Private void btSubmit_Click (object sender, EventArgs e)

{

This. Display ();

}

Next, write the KeyDown event of TextBox, and the code is as follows:

Private void tbxInput_KeyDown (object sender, KeyEventArgs e)

{

if(e . Control = = true & amp; & ampe; key code. ToString ()=="Return ")

{

This. Display ();

}

}

This method first detects whether the user pressed the Control and enter keys at the same time before performing the display operation.

The effects of program operation are as follows:

Press Control+ Enter to display text with the following effects:

C# Delegation and Event Problems

20

[Label: c# Delegation, Event Problem]

I don't quite understand the entrustment and time. Read "How to declare entrustment" and you will understand. However, it is not clear when the book talks about how to instantiate delegated use occasions. Declared delegate, the parameters of the delegate in the class are different from those declared. It's tangled Ask the master to explain to me in detail the use of entrustment.

Answer: 10 popularity: 10 solution time: 20 1 1-08-09 07:52.

Satisfied answer

Positive rate: 0%

Delegate is the core of the event mechanism in C#, which is often mythical on the Internet. Compare it to a threshold. Those who pass it are very happy, while those who fail are anxious and speechless outside the door.

This article will discuss with you the relationship between the implementation of delegation and the observer design pattern.

When learning C#, delegation is a threshold for me, and it is a very high threshold. I put it on the threshold several times, and then I fell headlong. I have been afraid of it for a long time. After reading many articles on the internet, it is hard and laborious to understand. It's not that people talk badly, but that people are too superficial. But online articles are mostly explained by examples and event mechanisms, which may be better understood by C++ programmers. To put it bluntly, a delegate is something like a pointer.

Before learning delegation, let's learn about the observer design pattern, which is well realized by delegation and time. First, give an example in head, and then give an example of weather forecast board, which will be transformed into a delegate-based implementation in C#.

This publishing house is going to publish a magazine. In order to better adapt to this market, the publishing house is full of tricks, and as a result, many readers have subscribed to this magazine. We regard the publishing house as a theme or an observer and the reader as an observer. When the publishing house updates the magazine, it will inform readers to get the latest content. Because magazines are becoming more and more popular, they attract more and more readers. If new readers want to get this magazine, they must order it from the publishing house. This process is understood as registration. Later, reader A was dissatisfied and didn't want to book it, so he applied for cancellation. Then the publishing house removed the list of reader A, and when a new issue of the magazine came out, reader A wouldn't be informed to get the information. Once reader A gets tired and wants magazines, he has to reorder.

As can be seen from the above example, the publishing house (subject or observed) has several actions, accepting a reader's order request, removing one reader and distributing the latest magazines to each reader.

The following code demonstrates how to implement a delegate-based system:

public class Public Publisher {

List scribe; //Save a new reader.

Public Publisher () {

this . scribers = new ArrayList();

}

Public Invalid Registrar (Registrar SC) (

scribers . add(sc);

}

Public void remove scribe (scribe sc) {

int index = scribers . index of(sc);

if(index & gt; 0)

scribers . remove(sc);

}

//It will be executed when there is a new magazine update.

public void newMagazine() {

for(int I = 0; I< scriber. Length; i++) {

Scriber sc =(Scriber)scribers . get(I);

sc . update();

}

}

}

Common class scriber (

//Contains a reference to the topic.

Private publisher pub

Public scribe (publisher publishing company) (

this.pub = pub

Pub.registerScriber (this); //register

}

Public void update () {

Sysout.out.println ("You have a new magazine! !" );

}

}

Common class test {

Public static void main(String[] args) {

Publisher pub = new Publisher();

Scribbler sc = new scribbler (pub);

pub . new magazine();

}

}

/* Output:

You have a new magazine! !

*/

The above example of readers and publishers demonstrates a simple observer model. When a new magazine is published, every reader will be informed. We can define multiple readers, that is, the relationship between publishers and readers is 1. Understand the observer model,