Last Updated:

Handling Events in .NET Using C #

Briefly

In this article, I'll talk about the event-handling model in .NET using C#. The discussion will begin with an introduction to the concept of delegates, and then expand to the concepts of events and their handling in .NET. Eventually, we'll apply the mechanism to Graphical User Interface (GUI) events using Windows forms. The discussion is accompanied by complete examples.

Introduction

Event handling is well known to those developers who have programmed the graphical user interface. When the user interacts with it (for example, by pressing a button), one or more methods waiting for this response are triggered. The event can be generated without user interaction. Event handlers are methods in an object that are bound to an event that is raised in an application. To understand the event handling mechanism, you need to understand the principles of delegates.

Delegates to C #

Delegates in C# allow you to apply methods of one class to objects of another class that can call those methods. You can apply the m method of class A defined in the delegate to class B, which will be able to call the m method of class A. You can call both static and non-static methods. This concept is well known to C++ developers who used a pointer to a function as a parameter passed to another function. The concept of delegates was introduced in Visual J++ and then moved to C#. C# delegates are an implementation in the .NET Framework as a derived class from System.Delegate. Using delegates can be described in four steps.

  1. Define a delegate object with a signature that exactly matches the signature of the method that you are trying to bind.
  2. To define the method with the delegate signature defined in the first step
  3. Create a delegate object and associate it with methods
  4. To call a linked method using a delegate object

The following C# code shows the above steps in implementing one delegate and four classes.

using System;
// Step 1. Defining a delegate with the signature of the bind method
public delegate void MyDelegate(string input);

// Step 2. Defining a method with the signature of a specific delegate
class MyClass1{
  public void delegateMethod1(string input){
    Console.WriteLine(
      "This is delegateMethod1 and the input to the method is {0}",
      input);
  }
  public void delegateMethod2(string input){
    Console.WriteLine(
     "This is delegateMethod2 and the input to the method is {0}",
     input);
  }
}

// Step 3: Create delegate objects and bind to methods
class MyClass2{
  public MyDelegate createDelegate(){
    MyClass1 c2=new MyClass1();
    MyDelegate d1 = new MyDelegate(c2.delegateMethod1);
    MyDelegate d2 = new MyDelegate(c2.delegateMethod2);
    MyDelegate d3 = d1 + d2;
    return d3;
  }
}

// Step 4. Call the method using the delegate
class MyClass3{
  public void callDelegate(MyDelegate d,string input){
    d(input);
  }
}
classDriver{
  static void Main(string[] args){
    MyClass2 c2 = new MyClass2();
    MyDelegate d = c2.createDelegate();
    MyClass3 c3 = new MyClass3();
    c3.callDelegate(d,"Calling the delegate");
  }
}

Event Handlers in C #

The event handler is a delegate with a special signature.

public delegate void MyEventHandler(object sender, MyEventArgs e);

The first parameter (sender) in the above definition defines the object that emits the event. The second parameter (e) contains the data to be used by the event handler. The MyEventArgs class must derive from the EventArgs class. EventArgs is the base class for more specialized classes such as MouseEventArgs, ListChangedEventArgs, etc. For event GUI, you can use the objects of these specialized classes without creating your own. However, for the rest of the events, you must have your own class and keep in it the data that you want to pass to the delegate. An example of creating your own class.

public class MyEventArgs  EventArgs{
  public string m_myEventArgumentdata;
}

In the case of an event handler, the delegate referenced by the object is marked with the event keyword.

public event MyEventHandler MyEvent;

Now we will look at the example of two classes how this mechanism works. In the second step of our discussion, the delegate demanded the definition of a method with the same signature. In our example, class A defines event handlers (methods with a signature similar to delegates). Next, we'll link them to the appropriate delegates. The method of class A will accept the object of class B with the help of a delegate. Then, when an event occurs in class B, the event handler, that is, the method of class A, will be called.

using System;
// Step 1
public delegate void MyHandler1(object sender, MyEventArgs e);
public delegate void MyHandler2(object sender, MyEventArgs e);

// Step 2
class A{
  public const string m_id="Class A";
  public void OnHandler1(object sender,MyEventArgs e){
    Console.WriteLine("I am in OnHandler1 and MyEventArgs is {0}",
                      e.m_id);
  }
  public void OnHandler2(object sender,MyEventArgs e){
    Console.WriteLine("I am in OnHandler2 and MyEventArgs is {0}",
                      e.m_id);
  }

  // Step 3
  public A(B b){
    MyHandler1 d1=new MyHandler1(OnHandler1);
    MyHandler2 d2=new MyHandler2(OnHandler2);
    b.Event1 +=d1;
    b.Event2 +=d2;
  }
}

// Step 4
class B{
  public event MyHandler1 Event1;
  public event MyHandler2 Event2;
  public void FireEvent1(MyEventArgs e){
    if(Event1 != null){
      Event1(this,e);
    }
  }
  public void FireEvent2(MyEventArgs e){
    if(Event2 != null){
      Event2(this,e);
    }
  }
}
public class MyEventArgs EventArgs{
  public string m_id;
}
public class Driver{
  public static void Main(){
    B b= new B();
    A a= new A(b);
    MyEventArgs e1=new MyEventArgs();
    MyEventArgs e2=new MyEventArgs();
    e1.m_id ="Event args for event 1";
    e2.m_id ="Event args for event 2";
    b.FireEvent1(e1);
    b.FireEvent2(e2);
  }
}

 

Handling GUI Events in C #

 

To handle Winfows Form events (the .NET Framework supports application GUI), the model described earlier is used. Let's look at the example of a simple application. Let's define the MyForm class, which inherits from the System.Windows.Forms.Form class. If you analyze the code and comments, you will notice that we do not define the delegate using the event keyword, because the events (mouse click, etc.) for GUI elements (form, button, etc.) are already available to you using the System.EvantHandler delegate. However, you still need to create a delegate object (System.EvantHandler) and embed it in the method that you want to respond to the event.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

public class MyForm  Form{
  private Button m_nameButton;
  private Button m_clearButton;
  private Label  m_nameLabel;

  private Container m_components = null;

  public MyForm(){
    initializeComponents();
  }
  private void initializeComponents(){
    m_nameLabel=new Label();
    m_nameButton = new Button();
    m_clearButton = new Button();

    SuspendLayout();

    m_nameLabel.Location=new Point(16,16);
    m_nameLabel.Text="Click NAME button, please";
    m_nameLabel.Size=new Size(300,23);

    m_nameButton.Location=new Point(16,120);
    m_nameButton.Size=new Size(176, 23);
    m_nameButton.Text="NAME";

    m_nameButton.Click += new System.EventHandler(NameButtonClicked);

    m_clearButton.Location=new Point(16,152);
    m_clearButton.Size=new Size(176,23);
    m_clearButton.Text="CLEAR";

    m_clearButton.Click += new System.EventHandler(ClearButtonClicked);

    this.ClientSize = new Size(292, 271);
    this.Controls.AddRange(new Control[] {m_nameLabel,
                                          m_nameButton,
                                          m_clearButton});
    this.ResumeLayout(false);
  }

  private void NameButtonClicked(object sender, EventArgs e){
    m_nameLabel.Text=
      "My name is john, please click CLEAR button to clear it";
  }
  private void ClearButtonClicked(object sender,EventArgs e){
    m_nameLabel.Text="Click NAME button, please";
  }
  public static void Main(){
    Application.Run(new MyForm());
  }

Conclusion

 

Other popular object-oriented languages like Java and Smalltalk do not contain delegate concepts in their arsenal. This is an innovation for C#, inherited from C++ and J++. I hope that the above discussion has clarified the concept to those programmers for whom C# is the first object-oriented language. If you are using the Visual Studio IDE for your C# GUI developments, the code for associating delegates with methods will be generated automatically by controlling the GUI (similar to clicking a mouse button). Analyzing this work is the best way to find out what is really hidden under the hood.