SUMMARY
This step-by-step article provides an introduction to delegates by using simple examples. Two examples of a singlecast delegate (that is, a delegate that is not combined) are provided. One example features a delegate in an object that is called from a Windows Form. The other provides a delegate on a form that can be invoked from a class. The multicast (or combined) delegate constructs an additional instance of the form delegate and demonstrates how to create a multicast delegate example that is comprised of both of the form callbacks.
If you are new to delegates, the examples in this article are what were formerly known as "callbacks". Delegates are type safe function pointers that integrate the ability to call multiple methods serially and support the calling of static methods and instance methods (native function pointers can only target static methods). The delegate functions in this example are very basic. Their function is to change the background color of a picture box.
The example in this article consists of a form with two picture boxes and three command buttons. Button1 demonstrates a class delegate that can be called from the form. Button2 demonstrates the opposite scenario: the delegate resides on the form, and is called from the class. Additionally, it demonstrates that a delegate can be passed to another entity. Button3 creates a multicast delegate that is composed of two form methods. The delegate, when executed, calls both of the form methods.
back to the top
Delegate from a Class
This example constructs a delegate in a class. The delegate is instantiated on the form so that the class method that is specified in the delegate can be called from the form. This example is not particularly practical because the same functionality can be accomplished by using a standard class method. It is offered here as a demonstration of how to establish this type of delegate if you ever need to do this.
//Define the delegate in the class.
delegate Color ClassCallback();
//Create an instance of the delegate on the form.
//Specifying the use of the changeColor method.
ClassCallback c=new ClassCallback(cbox.changeColor);
//Call the delegate function (changeColor).
this.textBox1.BackColor=c();
back to the top
Delegate from a Form
This example creates a delegate on a form that can be passed to the class (as opposed to the first example, where the delegate was not passed.) The class can then call the specified method through the delegate.
//Declare the delegate.
public delegate void FormCallback();
//Create an instance of the delegate.
FormCallback fc=new FormCallback(toggleColor);
//Pass the delegate to the class.
cbox.setCallback(fc);
//Accept the delegate in the class and invoke the method.
public void setCallback(FormCallback fc)
{
fc();
}
back to the top
Multicast Delegate from a Form
This example creates an additional instance of the delegate on the form. The purpose of the additional delegate is to demonstrate the construction of a multicast delegate. A multicast delegate is capable of calling more than one method. In this case, the delegate is comprised of two methods.
//Create an instance of the delegate.
FormCallback fc1=new FormCallback(toggleColor);
//create a second instance of the delegate
FormCallback fc2=new FormCallback(toggleOtherColor);
//Create a multicast delegate.
//Delegates can also be combined using the += operator.
FormCallback fc = fc1 + fc2;
//Pass the delegate to the class.
//Note that this does not require any changes to the class method.
cbox.setCallback(fc as FormCallback);
back to the top
Step-by-Step Example
- In Microsoft Visual C#, open a new Windows Application project. By default, Form1 is created.
- Open the code window for Form1.
- Replace the code in Form1 with the following:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
namespace delegateExample
{
public delegate void FormCallback();
public class displayForm : System.Windows.Forms.Form
{
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Forms.Button button1;
private System.ComponentModel.Container components = null;
private System.Windows.Forms.TextBox textBox2;
private System.Windows.Forms.Button button3;
private System.Windows.Forms.Button button4;
public displayForm()
{
InitializeComponent();
}
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
this.textBox1 = new System.Windows.Forms.TextBox();
this.button1 = new System.Windows.Forms.Button();
this.textBox2 = new System.Windows.Forms.TextBox();
this.button3 = new System.Windows.Forms.Button();
this.button4 = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// textBox1
//
this.textBox1.Font = new System.Drawing.Font("Microsoft Sans Serif", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
this.textBox1.Location = new System.Drawing.Point(16, 16);
this.textBox1.Multiline = true;
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(64, 96);
this.textBox1.TabIndex = 0;
this.textBox1.Text = "";
this.textBox1.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
//
// button1
//
this.button1.Location = new System.Drawing.Point(16, 136);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(64, 56);
this.button1.TabIndex = 1;
this.button1.Text = "Delegate in Object";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// textBox2
//
this.textBox2.Location = new System.Drawing.Point(104, 16);
this.textBox2.Multiline = true;
this.textBox2.Name = "textBox2";
this.textBox2.Size = new System.Drawing.Size(64, 96);
this.textBox2.TabIndex = 3;
this.textBox2.Text = "";
//
// button3
//
this.button3.Location = new System.Drawing.Point(104, 136);
this.button3.Name = "button3";
this.button3.Size = new System.Drawing.Size(64, 56);
this.button3.TabIndex = 4;
this.button3.Text = "Delegate in Form";
this.button3.Click += new System.EventHandler(this.button3_Click);
//
// button4
//
this.button4.Location = new System.Drawing.Point(192, 64);
this.button4.Name = "button4";
this.button4.Size = new System.Drawing.Size(75, 128);
this.button4.TabIndex = 5;
this.button4.Text = "Multicast Delegate";
this.button4.Click += new System.EventHandler(this.button4_Click);
//
// displayForm
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 266);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.button4,
this.button3,
this.textBox2,
this.button1,
this.textBox1});
this.Name = "displayForm";
this.Text = "Delegates Example";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
}
#endregion
colorBox cbox;
bool toggle=false;
bool othertoggle=false;
[STAThread]
static void Main()
{
Application.Run(new displayForm());
}
private void Form1_Load(object sender, System.EventArgs e)
{
cbox=new colorBox();
}
private void button1_Click(object sender, System.EventArgs e)
{
ClassCallback c=new ClassCallback(cbox.changeColor);
this.textBox1.BackColor=c();
}
public void toggleColor()
{
toggle=!toggle;
if (toggle)
{
this.textBox2.BackColor= Color.Red;
}
else
{
this.textBox2.BackColor=Color.Goldenrod;
}
}
public void toggleOtherColor()
{
othertoggle=!othertoggle;
if (toggle)
{
this.textBox1.BackColor= Color.Red;
}
else
{
this.textBox1.BackColor=Color.Goldenrod;
}
}
private void button3_Click(object sender, System.EventArgs e)
{
FormCallback fc=new FormCallback(toggleColor);
cbox.setCallback(fc);
}
private void button4_Click(object sender, System.EventArgs e)
{
FormCallback fc1=new FormCallback(toggleColor);
FormCallback fc2=new FormCallback(toggleOtherColor);
FormCallback fc = fc1 + fc2;
cbox.setCallback(fc as FormCallback);
}
}
}
- Add a class to the project.
- Replace the code in the class with the following:
using System;
using System.Drawing;
namespace delegateExample
{
// Delegate to provide a callback in the class.
// This callback is used by the form.
delegate Color ClassCallback();
// Class to demonstrate delegate use. Delegates are
// provided so that the Form can call back to the class and the
// class can call back to the Form.
public class colorBox
{
/// <summary>
/// Boolean flag used to toggle colors.
/// </summary>
private bool toggle=true;
/// <summary>
/// Class Constructor
/// </summary>
public colorBox()
{
}
// Method that is provided to the form
// for use in the callback.
public Color changeColor()
{
toggle=!toggle;
if (toggle)
{
return Color.Red;
}
else
{
return Color.Goldenrod;
}
}
// Function that receives and executes the
// delegate (callback) from the form.
public void setCallback(FormCallback fc)
{
fc();
}
}
}
Note The code should be changed in Visual Studio 2005. When you create a Windows Forms project, Visual C# adds one form to the project by default. This form is named Form1. The two files that represent the form are named Form1.cs and Form1.designer.cs. You write your code in Form1.cs. The designer.cs file is where the Windows Forms Designer writes the code that implements all the actions that you performed by dragging and dropping controls from the Toolbox.
For more information about the Windows Forms Designer in Visual C# 2005, visit the following Microsoft Web site:
- Run the project.
- As you click the buttons, the delegate methods are called to change the colors of the picture boxes.
back to the top