Sunteți pe pagina 1din 20

Delegates and Event Handling in C#

Overview
All of us have been exposed to event driven programming of some sort or the other. C# adds on
value to the often mentioned world of event driven programming by adding support through
events and delegates. The emphasis of this article would be to identify what exactly happens
when you add an event handler to your common UI controls. A simple simulation of what could
possibly be going on behind the scenes when the AddOnClick or any similar event is added to the
Button class will be explained. This will help you understand better the nature of event handling
using multi cast delegates.

Delegates
A delegate in C# is similar to a function pointer in C or C++. Using a delegate allows the
programmer to encapsulate a reference to a method inside a delegate object. The delegate object
can then be passed to code which can call the referenced method, without having to know at
compile time which method will be invoked.

Call a Function directly - No Delegate


In most cases, when we call a function, we specify the function to be called directly. If the class
MyClass has a function named Process, we'd normally call it like this (SimpleSample.cs):
using System;

namespace Akadia.NoDelegate
{
public class MyClass
{
public void Process()
{
Console.WriteLine("Process() begin");
Console.WriteLine("Process() end");
}
}

public class Test


{
static void Main(string[] args)
{
MyClass myClass = new MyClass();
myClass.Process();
}
}
}

That works well in most situations. Sometimes, however, we don't want to call a function directly
- we'd like to be able to pass it to somebody else so that they can call it. This is especially useful
in an event-driven system such as a graphical user interface, when I want some code to be
executed when the user clicks on a button, or when I want to log some information but can't
specify how it is logged.

The very basic Delegate


An interesting and useful property of a delegate is that it does not know or care about the class of
the object that it references. Any object will do; all that matters is that the method's argument
types and return type match the delegate's. This makes delegates perfectly suited for
"anonymous" invocation.

The signature of a single cast delegate is shown below:


delegate result-type identifier ([parameters]);
where:
o result-type: The result type, which matches the return type of the function.
o identifier: The delegate name.
o parameters: The Parameters, that the function takes.

Examples:
public delegate void SimpleDelegate ()
This declaration defines a delegate named SimpleDelegate, which will encapsulate any method
that takes no parameters and returns no value.

public delegate int ButtonClickHandler (object obj1, object obj2)


This declaration defines a delegate named ButtonClickHandler, which will encapsulate any
method that takes two objects as parameters and returns an int.

A delegate will allow us to specify what the function we'll be calling looks like without
having to specify which function to call. The declaration for a delegate looks just like the
declaration for a function, except that in this case, we're declaring the signature of functions that
this delegate can reference.
There are three steps in defining and using delegates:
1. Declaration
2. Instantiation
3. Invocation

A very basic example (SimpleDelegate1.cs):


using System;

namespace Akadia.BasicDelegate
{
// Declaration
public delegate void SimpleDelegate();

class TestDelegate
{
public static void MyFunc()
{
Console.WriteLine("I was called by delegate...");
}

public static void Main()


{
// Instantiation
SimpleDelegate simpleDelegate = new SimpleDelegate(MyFunc);
// Invocation
simpleDelegate();
}
}
}

Compile and test:


# csc SimpleDelegate1.cs
# SimpleDelegate1.exe

I was called by delegate...

Calling Static Functions


For our next, more advanced example (SimpleDelegate2.cs), declares a delegate that takes a
single string parameter and has no return type:
using System;

namespace Akadia.SimpleDelegate
{
public class MyClass
{
// Declare a delegate that takes a single string parameter and has no return type.
public delegate void LogHandler(string message);

// The use of the delegate is just like calling a function directly,


// though we need to add a check to see if the delegate is null
// (that is, not pointing to a function) before calling the function.
public void Process(LogHandler logHandler)
{
if (logHandler != null)
logHandler("Process() begin");

if (logHandler != null)
logHandler ("Process() end");
}
}

// Test Application to use the defined Delegate


public class TestApplication
{
// Static Function: To which is used in the Delegate. To call the Process() function, we
//need to declare a logging function: Logger() that matches the signature of the delegate.
static void Logger(string s)
{
Console.WriteLine(s);
}

static void Main(string[] args)


{
MyClass myClass = new MyClass();

// Crate an instance of the delegate, pointing to the logging function.


// This delegate will then be passed to the Process() function.
MyClass.LogHandler myLogger = new MyClass.LogHandler(Logger);
myClass.Process(myLogger);
}
}
}

Compile an test:
# csc SimpleDelegate2.cs
# SimpleDelegate2.exe

Process() begin
Process() end

Calling Member Functions


In the simple example above, the Logger( ) function merely writes the string out. A different
function might want to log the information to a file, but to do this, the function needs to know
what file to write the information to (SimpleDelegate3.cs)
using System;
using System.IO;
namespace Akadia.SimpleDelegate
{
// Delegate Specification
public class MyClass
{
// Declare a delegate that takes a single string parameter and has no return type.
public delegate void LogHandler(string message);

// The use of the delegate is just like calling a function directly,


// though we need to add a check to see if the delegate is null
// (that is, not pointing to a function) before calling the function.
public void Process(LogHandler logHandler)
{
if (logHandler != null)
logHandler("Process() begin");

if (logHandler != null)
logHandler ("Process() end");
}
}

// The FileLogger class merely encapsulates the file I/O


public class FileLogger
{
FileStream fileStream;
StreamWriter streamWriter;

public FileLogger(string filename)


{
fileStream = new FileStream(filename, FileMode.Create);
streamWriter = new StreamWriter(fileStream);
}

// Member Function which is used in the Delegate


public void Logger(string s)
{
streamWriter.WriteLine(s);
}

public void Close()


{
streamWriter.Close();
fileStream.Close();
}
}

// Main() is modified so that the delegate points to the Logger()function on the fl instance
// of a FileLogger. When this delegate is invoked from Process(), the member function is called
// and the string is logged to the appropriate file.
public class TestApplication
{
static void Main(string[] args)
{
FileLogger fl = new FileLogger("process.log");

MyClass myClass = new MyClass();

// Crate an instance of the delegate, pointing to the Logger()


// function on the fl instance of a FileLogger.
MyClass.LogHandler myLogger = new MyClass.LogHandler(fl.Logger);
myClass.Process(myLogger);
fl.Close();
}
}
}

The cool part here is that we didn't have to change the Process() function; the code to all the
delegate is the same regardless of whether it refers to a static or member function.
Compile an test:
# csc SimpleDelegate3.cs
# SimpleDelegate3.exe
# cat process.log

Process() begin
Process() end

Multicasting
Being able to point to member functions is nice, but there are more tricks you can do with
delegates. In C#, delegates are multicast, which means that they can point to more than one
function at a time (that is, they're based off the System.MulticastDelegate type). A multicast
delegate maintains a list of functions that will all be called when the delegate is invoked. We can
add back in the logging function from the first example, and call both delegates. Here's what the
code looks like:
using System;
using System.IO;
namespace Akadia.SimpleDelegate
{
// Delegate Specification
public class MyClass
{
// Declare a delegate that takes a single string parameter and has no return type.
public delegate void LogHandler(string message);
// The use of the delegate is just like calling a function directly,
// though we need to add a check to see if the delegate is null
// (that is, not pointing to a function) before calling the function.
public void Process(LogHandler logHandler)
{
if (logHandler != null)
{
logHandler("Process() begin");
}
if (logHandler != null)
{
logHandler ("Process() end");
}
}
}

// The FileLogger class merely encapsulates the file I/O


public class FileLogger
{
FileStream fileStream;
StreamWriter streamWriter;

public FileLogger(string filename)


{
fileStream = new FileStream(filename, FileMode.Create);
streamWriter = new StreamWriter(fileStream);
}

// Member Function which is used in the Delegate


public void Logger(string s)
{
streamWriter.WriteLine(s);
}
public void Close()
{
streamWriter.Close();
fileStream.Close();
}
}

// Test Application which calls both Delegates


public class TestApplication
{
// Static Function which is used in the Delegate
static void Logger(string s)
{
Console.WriteLine(s);
}
static void Main(string[] args)
{
FileLogger fl = new FileLogger("process.log");
MyClass myClass = new MyClass();

// Crate an instance of the delegates, pointing to the static


// Logger() function defined in the TestApplication class and
// then to member function on the fl instance of a FileLogger.
MyClass.LogHandler myLogger = null;
myLogger += new MyClass.LogHandler(Logger);
myLogger += new MyClass.LogHandler(fl.Logger);
myClass.Process(myLogger);
fl.Close();
}
}
}

Compile an test:
# csc SimpleDelegate4.cs
# SimpleDelegate4.exe

Process() begin
Process() end

# cat process.log
Process() begin
Process() end

Events
The Event model in C# finds its roots in the event programming model that is popular in
asynchronous programming. The basic foundation behind this programming model is the idea of
"publisher and subscribers." In this model, you have publishers who will do some logic and
publish an "event." Publishers will then send out their event only to subscribers who have
subscribed to receive the specific event.
In C#, any object can publish a set of events to which other applications can subscribe. When the
publishing class raises an event, all the subscribed applications are notified. The following figure
shows this mechanism.

Conventions
The following important conventions are used with events

Event Handlers in the .NET Framework return void and take two parameters. The first
parameter is the source of the event; that is the publishing object. The second
parameter is an object derived from EventArgs. Events are properties of the class
publishing the event. The keyword event controls how the event property is accessed by
the subscribing classes.

Simple Event
Let's modify our logging example from above to use an event rather than a delegate:
using System;
using System.IO;

namespace Akadia.SimpleEvent
{
/* ========= Publisher of the Event ============== */
public class MyClass
{
// Define a delegate named LogHandler, which will encapsulate
// any method that takes a string as the parameter and returns no value
public delegate void LogHandler(string message);
// Define an Event based on the above Delegate
public event LogHandler Log;

// Instead of having the Process() function take a delegate


// as a parameter, we've declared a Log event. Call the Event,
// using the OnXXXX Method, where XXXX is the name of the Event.
public void Process()
{
OnLog ("Process() begin");
OnLog ("Process() end");
}

// By Default, create an OnXXXX Method, to call the Event


protected void OnLog(string message)
{
if (Log != null)
Log (message);
}
}

// The FileLogger class merely encapsulates the file I/O


public class FileLogger
{
FileStream fileStream;
StreamWriter streamWriter;

// Constructor
public FileLogger(string filename)
{
fileStream = new FileStream(filename, FileMode.Create);
streamWriter = new StreamWriter(fileStream);
}

// Member Function which is used in the Delegate


public void Logger(string s)
{
streamWriter.WriteLine(s);
}

public void Close()


{
streamWriter.Close();
fileStream.Close();
}
}

/* ================= Subscriber of the Event ================== */


// It's now easier and cleaner to merely add instances of the delegate to the event, instead of
// having to manage things ourselves
public class TestApplication
{
static void Logger(string s)
{
Console.WriteLine(s);
}

static void Main(string[] args)


{
FileLogger fl = new FileLogger("process.log");

MyClass myClass = new MyClass();

myClass.Log += new MyClass.LogHandler(Logger);


myClass.Log += new MyClass.LogHandler(fl.Logger);
myClass.Process();

fl.Close();
}
}
}

Compile an test:
# csc SimpleEvent.cs
# SimpleEvent.exe

Process() begin
Process() end

# cat process.log

Process() begin
Process() end

The Second Change Event Example


Suppose you want to create a Clock class that uses events to notify potential subscribers
whenever the local time changes value by one second. Here is the complete, documented
example:
using System;
using System.Threading;

namespace SecondChangeEvent
{
/* ====================== Event Publisher ==================== */

// Our subject -- it is this class that other classes will observe. This class publishes one event:
// SecondChange. The observers subscribe to that event.
public class Clock
{
// Private Fields holding the hour, minute and second
private int _hour;
private int _minute;
private int _second;

// The delegate named SecondChangeHandler, which will encapsulate any method that takes
// a clock object and a TimeInfoEventArgs object as the parameter and returns no value. It's
// the delegate the subscribers must implement.
public delegate void SecondChangeHandler (
object clock, TimeInfoEventArgs timeInformation);

// The event we publish


public event SecondChangeHandler SecondChange;

// The method which fires the Event


protected void OnSecondChange(
object clock, TimeInfoEventArgs timeInformation
)
{
// Check if there are any Subscribers
if (SecondChange != null)
{
// Call the Event
SecondChange(clock,timeInformation);
}
}

// Set the clock running, it will raise an event for each new second
public void Run()
{
for(;;)
{
// Sleep 1 Second
Thread.Sleep(1000);

// Get the current time


System.DateTime dt = System.DateTime.Now;

// If the second has changed notify the subscribers


if (dt.Second != _second)
{
// Create the TimeInfoEventArgs object to pass to the subscribers
TimeInfoEventArgs timeInformation =
new TimeInfoEventArgs(dt.Hour, dt.Minute, dt.Second);

// If anyone has subscribed, notify them


OnSecondChange (this,timeInformation);
}

// update the state


_second = dt.Second;
_minute = dt.Minute;
_hour = dt.Hour;

}
}
}

// The class to hold the information about the event in this case it will hold only information
// available in the clock class, but could hold additional state information
public class TimeInfoEventArgs : EventArgs
{
public TimeInfoEventArgs(int hour, int minute, int second)
{
this.hour = hour;
this.minute = minute;
this.second = second;
}

public readonly int hour;


public readonly int minute;
public readonly int second;
}

/* =================== Event Subscribers ==================== */


// An observer. DisplayClock subscribes to the clock's events. The job of DisplayClock is
// to display the current time
public class DisplayClock
{
// Given a clock, subscribe to its SecondChangeHandler event
public void Subscribe(Clock theClock)
{
theClock.SecondChange += new Clock.SecondChangeHandler(TimeHasChanged);
}

// The method that implements the delegated functionality


public void TimeHasChanged(
object theClock, TimeInfoEventArgs ti)
{
Console.WriteLine("Current Time: {0}:{1}:{2}",
ti.hour.ToString(), ti.minute.ToString(), ti.second.ToString());
}
}

// A second subscriber whose job is to write to a file


public class LogClock
{
public void Subscribe(Clock theClock)
{
theClock.SecondChange += new Clock.SecondChangeHandler(WriteLogEntry);
}

// This method should write to a file we write to the console to see the effect
// this object keeps no state
public void WriteLogEntry(object theClock, TimeInfoEventArgs ti)
{
Console.WriteLine("Logging to file: {0}:{1}:{2}",
ti.hour.ToString(), ti.minute.ToString(), ti.second.ToString());
}
}

/* ==================== Test Application ==================== */

// Test Application which implements the Clock Notifier - Subscriber Sample


public class Test
{
public static void Main()
{
// Create a new clock
Clock theClock = new Clock();

// Create the display and tell it to subscribe to the clock just created
DisplayClock dc = new DisplayClock();
dc.Subscribe(theClock);

// Create a Log object and tell it to subscribe to the clock


LogClock lc = new LogClock();
lc.Subscribe(theClock);

// Get the clock started


theClock.Run();
}
}
}

Conclusion
The Clock class from the last sample could simply print the time rather than raising an event, so
why bother with the introduction of using delegates? The advantage of the subscribe idiom
is that any number of classes can be notified when an event is raised. The subscribing
classes do not need to know how the Clock works, and the Clock does not need to know what
they are going to do in response to the event. Similarly a button can publish an OnClick event,
and any number of unrelated objects can subscribe to that event, receiving notification when the
button is clicked.
The publisher and the subscribers are decoupled by the delegate. This is highly desirable
as it makes for more flexible and robust code. The clock can change how it detects time without
breaking any of the subscribing classes. The subscribing classes can change how they respond to
time changes without breaking the Clock. The two classes spin independently of one another,
which makes for code that is easier to maintain.

*********************************************************************

Introduction:
This article will deal with Event and delegates in C#. C# Open a new door by including the feature
of Event Driven programming such as Events and Delegates. This article is part of the series that
helps in understanding Events and Delegates.
Events are the means by which Windows Application receive notification. In a Windows application
a lot of Events are occurring at a particular instant for e.g. Mouse Move, Mouse out, Mouse Click
etc. Delegates are pointer to the function and are type-safe. This Article will cover the Single
delegate, Multi-cast delegates and Event Driven programming using C#. The first part of this
article will focus delegates and its types and the remaining part is on Events.

Delegates:
Another very interesting feature in C# is delegates. Delegates are best complemented as new
type of Object in C#. They are also represented as pointer to functions. Technically delegate is a
reference type used to encapsulate a method with a specific signature and return type. Since in
this article delegate discussion is event centric. If we consider a real world scenario then
delegates can be understood as any delegate representing a country a group of people
representing a company etc. This same definition can be mapped to C# as delegate act as an
intermediary between event source and destination. The .NetFrameWork has a Name Space
System.Delegate. We have two flavors of delegate in C#.

 Single Delegate
 Multi-cast Delegate

Single Delegates:
A delegate is called a single delegate that derives from the System.Delegate class contains an
invocation list with one method. Now we will look at how the single-cast delegates are declared.
In single-cast delegates, the delegate can point to both static and non-static method if both have
the same signature as the delegate. Look at the code below how to declare a single-cast delegate.
public delegate void Myfunction(string,System.Int32)

The above code shows a simple delegate which will point to a method with no return type and
taking two arguments as parameters. Now we see delegate that return a value.
public delegate bool MyFunctionOne();

Consider a simple example


using System;
namespace ConsoleApplication
{
public class Name
{
public Name()
{
// TODO: Add constructor logic here
}

public string Compare(string NameOne, string NameTwo)


{
System.Int32 result=NameOne.CompareTo(NameTwo);

if(result==0)
{
return NameOne;
}
else
{
Console.WriteLine(NameTwo +""+ NameTwo);
return NameTwo+" "+NameOne;
}
}
}
}

Description of the Above Code:


The above example doesn't show the true usage of delegates but I think we are getting the idea
what we want to understand. Above is a simple program which compares two strings. If the
strings are equal then only one name is returned otherwise both the names are returned if the
condition executes to false. Now first the main method is invoked which is situated in Delegate
Example Class. In this class we have also declared our delegate.
public delegate string CompareNames(string NameOne,string NameTwo);

It accepts two arguments of type string and also returns a string. In the main method we create
the instance of Name class and then we create the instance of our delegate passing the name of
our method in it as its argument so that it points to compare method now. Then we just call our
delegates by passing the arguments. Which in return call the Compare method and return the
string.

Multi-cast Delegates:
A delegate is called Multi-cast Delegate that derives from the System.MulticastDelegate contains
an invocation list with multiple methods. At times it is desirable to call two methods through a
single delegate. This can be achieved through Single-cast Delegate but it is different from having
a collection, each of which invokes a single method.

In Multi-casting you create a single delegate that will invoke multiple encapsulated methods. The
return type of all the delegates should be same. Now the question why are we using Multi-cast
delegates when Single-cast delegates are enough. Well the answer to this question is what if you
want to call three methods when a button is clicked. The Multi-cast delegates are used with
events where multiple call to different methods are required. System.MulticastDelegate contains
two methods Combine and Remove. The Combine is a static method of class
System.MulticastDelegate and is used to combine the delegates and the remove method is used
to remove the delegate from the list. For user convenience we have += operator overloaded for
delegate Combine method and -= operator overloaded for Remove method Multi-cast delegates
are similar to Single-cast delegates for e.g.
public delegate void MulticastDelegate();

Multi-cast delegate can have arguments and can return value as well. All the Methods pointed by
delegates should return the similar value as the delegate return type.
public delegate string MultiCastOne(string Name);

Consider a simple example:


using System;

namespace Multi_castDelegate
{
class MyClassDelegate
{
public delegate string StringDelegate(string s);
}
}

Below is the class that defines the static methods having same signature as delegate.
using System;

namespace Multi_castDelegate
{
public class MyClass
{
public MyClass(){}

public static string WriteString(string s)


{
Console.WriteLine("Writing string");
return "null";
}

public static string logString(string s)


{
Console.WriteLine("loging string");
return "null";
}

public static string TransmitString(string s)


{
Console.WriteLine("Transmitting string");
return "null";
}
}
}

The Main class:


using System;
using System.Threading;
namespace Multi_castDelegate
{
public class Test
{
public static void Main()
{
MyClassDelegate.StringDelegate Writer, Logger, Transmitter;
MyClassDelegate.StringDelegate myDelegate;

Writer = new MyClassDelegate.StringDelegate(MyClass.WriteString);


Writer("Hello I am Writer just acting like Single cast");

Logger = new MyClassDelegate.StringDelegate(MyClass.logString);


Logger("Hello I am Logger just acting like Single-cast");

Transmitter = new MyClassDelegate.StringDelegate(MyClass.TransmitString);


Transmitter("Hello I am Transmitter just acting like Single-cast");

// Here mydelegate used the Combine method of System.MulticastDelegate


// and the delegates combine
myDelegate = (MyClassDelegate.StringDelegate)
System.Delegate.Combine(Writer, Logger);
myDelegate("used Combine");

// Here Transmitter is also added using the overloaded form of Combine


myDelegate += Transmitter;
myDelegate("Using Overloaded Form");

// Now using the Remove method


myDelegate = (MyClassDelegate.StringDelegate)
System.Delegate.Remove(myDelegate,Writer);
myDelegate("Without Writer");

// Overloaded Remove
myDelegate-=Transmitter;
myDelegate("Without Transmitter");
System.Threading.Thread.Sleep(2300);
}
}
}

Description of the Above Code:


The above program contains three classes, MyClassDelegate contains the delegate.
public delegate string StringDelegate(string s);

The class MyClass contains the static methods that contains the static methods that have a
similar signature as the delegate StringDelegate. The third class is the Test Class which shows
how to combine the delegates and how to remove the delegate from the list.

Events:
Events are the messages sent by an object to indicate the occurrence of an event. Event can also
be defined as a member that enables an object to provide notification. Events provide a very
powerful means of inter-process communication. The most familiar example of events are
graphical user interface, events are fired when any control is clicked on the GUI.
Events are not used only for graphical user interfaces. Events provide a generally useful way for
objects to signal state changes that may be useful to the client of that object. In C# events are
used with delegates. If you don't have through understanding of delegates please refer the above
portion. In event communication the event raiser class doesn't know who is going to handle the
event now the delegates comes into play that acts as an intermediary between the source and the
receiver.

Delegate:
public delegate void newdelegate();

Event Declaration:
public event newdelegate newevent;

We can categories events into two types


 Customized Events
 Predefined Events
1. Customized Events:
Don't confuse these terms because I have categorized events so that the explanation become
simple. Now what do we mean by customize events, they are events which we define according to
our needs and are not defined. For e.g. we want to raise an event whenever a dynamic control is
created on the form. To declare an event, first define the delegate for that event, if none is
already declared. The delegate type defines the set of argument that are to be passed to the
method which will act as event handler.

Example of Customized Events:


namespace Eventhandling
{
public delegate void IamClicked();

public class Form1 : System.Windows.Forms.Form


{
private System.ComponentModel.Container components = null;
public System.Int32 o_IntCounter=0;
public event IamClicked ClickMe;
System.Int32 o_intXaxis=120;
System.Int32 o_intYaxis=80;

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
Button b1 = new Button();
b1.Parent = this;
b1.Location = new Point(o_intXaxis, o_intYaxis);
b1.Name="Click1";
b1.Text="Click Me";
ClickMe += new IamClicked(Show);
ClickMe();
}

protected override void Dispose( bool disposing )


{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code


/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(304, 237);
this.Name = "Form1";
this.Text = "Events";
}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
/// <summary>
/// Event Handler Function Which is called when the
/// Click Event is Raised.
/// </summary>
/// <param name="o"></param>
/// <param name="ea"></param>
public void Show()
{
MessageBox.Show("JUST BORN");
}
}
}

Description:
The above program shows hoe we can fire our own events. In this program a button is created
dynamically.
Button b1=new Button();
b1.Parent=this;
b1.Location=new Point(o_intXaxis,o_intYaxis);
b1.Name="Click1";
b1.Text="Click Me";
ClickMe+=new IamClicked(Show);
ClickMe();

The delegate and event defined in above program are


public delegate void IamClicked();
public event IamClicked ClickMe;

The delegate points to the following function.


public void Show()
{
MessageBox.Show("JUST BORN");
}

When the ClickME event is fired the delegate attached to this event call the above function Show.
Look at the signature of the function and the delegate both are same. The function just shows a
message box with the message "Just Born".

2. Predefined Events:
Events and delegates go hand in hand. Now we are considering Predefined events like
 Click
 Closed
 Closing
 DragDrop
 Enter
 Load
 Leave
etc…

We normally use predefined events in our programming practice. Multiple events can share the
same delegate type. The event is declared as the delegate type. In C# we must follow precise
signature for Handler.
void OnClick(object o,EventArgs ea)
{
//Code
}

Example of Events:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

namespace Eventhandling
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public System.Int32 o_IntCounter=0;
private System.Windows.Forms.Button btnNewControl;

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after InitializeComponent call
//
}

/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code


/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.btnNewControl = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// btnNewControl
//
this.btnNewControl.Name = "btnNewControl";
this.btnNewControl.Size = new System.Drawing.Size(112, 32);
this.btnNewControl.TabIndex = 0;
this.btnNewControl.Text = "New Control";
this.btnNewControl.Click += new System.EventHandler(this.btnNewControl_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(304, 237);
this.Controls.AddRange(new System.Windows.Forms.Control[]
{
this.btnNewControl});
this.Name = "Form1";
this.Text = "Events";
this.ResumeLayout(false);
}
#endregion

/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}

/// <summary>
/// Event Handler Function Which is called when the
/// Click Event is Raised.
/// </summary>
/// <param name="o"></param>
/// <param name="ea"></param>
public void btnAdd(object o,EventArgs ea)
{
o_IntCounter++;
MessageBox.Show(o_IntCounter.ToString());
}
private void btnNewControl_Click(object sender, System.EventArgs e)
{
System.Int32 b_intCount;
System.Int32 b_intXaxis=120;
System.Int32 b_intYaxis=80;
for(b_intCount=1;b_intCount<=3;b_intCount++,b_intYaxis+=20)
{
///new buttons are created at run time
///with there location and names.
Button b1=new Button();
b1.Parent=this;
b1.Location=new Point(b_intXaxis,b_intYaxis);
b1.Name="Click1"+b_intCount;
b1.Text="Click Me";
b1.Click+=new EventHandler(btnAdd);
}
}
}
}

Description:
The above program creates three buttons at run time and when any of the buttons is clicked the
Click event of that button is fired.
for(b_intCount=1;b_intCount<=3;b_intCount++,b_intYaxis+=20)
{
///new buttons are created at run time
///with there location and names.
Button b1=new Button();
b1.Parent=this;
b1.Location=new Point(b_intXaxis,b_intYaxis);
b1.Name="Click1"+b_intCount;
b1.Text="Click Me";
b1.Click+=new EventHandler(btnAdd);
}

The Click event belongs to the button class. We will reference it when we are registering a
delegate.
b1.Click+=new EventHandler(btnAdd);

The delegate EventHandler is also defined in the System namespace of Dot net Framework
library. All what we have to do is to define our callback function that is invoked when the button is
clicked and accepts two arguments object and EventArgs type conforms the signature of delegate
EventHandler defined in System namespace
public void btnAdd(object o,EventArgs ea)
{
o_IntCounter++;
MessageBox.Show(o_IntCounter.ToString());
}

The handler btnAdd() Method catches this event and shows a message box that indicates a
number that how many times these buttons are clicked. The above example is quite self
explanatory so just copy the code in a new project and run for yourself.

S-ar putea să vă placă și