This article will talk about the On Click Event in C#.
These events get fired when we click on a button for example.
To understand such events we need to put ourselves in the shoes of the developers who made these buttons but first, we need to learn about delegates!.
The Problem
Imagine we are developing a UI Library that other developers can use to build mobile apps.
And one of the UI elements that other developers can use (Drag and drop) is a button.
If we look at the code behind the button class used to create the green button below.
A button like this will have the following properties:
//Properties : public string text;//A string called text with the value “Send”. public Color backColor;//A Color called backColor which is somewhat greenish. public int sizeW, sizeH;//Two ints called sizeW and sizeH for the width and height of the button.
Now what is missing here is the method that contains the code that needs to be executed once the button is clicked.
Now we have a problem here.
We as the developers who made this UI system cannot tell what the other developers using our UI system want the button to do when it’s clicked.
The Solution
That’s why we need to provide the OnClick event as a delegate and not as a normal method.
And since a delegate is a variable that can store a reference to a method, other developers can write their own implementation inside a method that contains the logic they want to be executed on click, and assign it to the buttons onClick delegate/event we provided.
Our onClick delegate can be defined like this :
private delegate void OnClickDelegate();
Now let’s break it down bit by bit.
We will start by writing the access specifier.
Followed by the Delegate keyword, which tells the compiler that we are defining a new delegate type.
Finally, we need to specify the type of methods our delegate can store. And by type I mean the return type and the parameters.
OnClickDelegate the name of the delegate we just defined.
Now the next step is to actually create a variable of this new delegate type.
So we define it just like we define any variable in C# by starting with public then the type of the variable we are creating which is OnClickDelegate and lastly the variable name which is OnClick.
So how can the other developers use this new Delegate to execute their own code?.
public OnClickDelegate OnClick;
Let’s say the other developers dragged and dropped a button into the canvas in the IDE they are using to develop this mobile app using our UI system.
Which resulted in the creation of a button object.
Let’s assume the name of this button is SendButton.
First, they will have to add the logic they want to execute when the button is clicked.
Let’s say they want to connect to the network, send a message then display a message to the user, whenever the button is clicked.
void SendButtonClick(){ Network.Connect(); Network.SendMessage(); DisplayMessageSentDialog(); }
So now they have a method Called SendButtonClick that is not yet connected to the button in any way.
To fix that.
They need to assign their method to our OnClick Delegate that belongs to the button object.
SendButton.OnClick = SendButtonClick;
Note we wrote our method name without the ( ) because we are not calling it we are just storing its reference in the OnClick delegate.
Now under the hood in our UI system, if the mouse was hovering over the button and the mouse was clicked.
if(IsMouseHovering && IsLeftClickPressed ){ SendButton.OnClick(); }
Our UI system will call the OnClick delegate of our SendButton which will in return call any methods that were assigned to it.
In this case, it will call the SendButtonClick, and the message sent dialog will be displayed.
This way whoever uses our UI system can create their own methods, then assign their methods to our delegates and we can call them whenever the conditions are met : ).
We are not limited to onClick events we can even create delegates for when the application starts or closes for example.
This was a very abstract example, but this is a real use case of delegates in general.
Creating our Own Delegates
So let’s see delegates in action.
To understand delegates better, we will start by using a delegate that already exists in C#.
So, first of all, let’s start by defining a simple list of strings called names.
//list of names
List<string> names = new List<string>() { "Aiden", "Sif", "Walter", "Anatoli" };
We want to remove all the names in our list that satisfy a specific condition or maybe conditions.
Luckily any list in C# contains a method called RemoveAll, so let’s use it.
If we write it like this, you will notice an error; this is because the RemoveAll is expecting a method that matches a delegate called Predicate, So let’s click on it and see how it’s defined.
We can see that the Predicate is a delegate that takes an object of T (which means specific type. In this case, T is the type of our list elements (string)).
And returns a bool.
When we call the RemoveAll method, this Predicate will be called on every name in our list.
If we read the documentation, we will learn that the bool that is returned by this Predicate will determine whether or not this element will be removed from the list. If it returns true, then the element will be removed.
And it is our job to write these rules that determine the fate of the names in our list : ).
After all, the people who wrote the code behind the RemoveAll method can’t read our minds to determine the rules we want exactly. That’s why we will create our own method that matches the definition of the Predicate delegate and pass it to the RemoveAll method : ).
Let’s say we want to remove all the names that contain the letter ‘i’.
Adding our Filters
We can write our filtration method like so.
//a method called Filter that takes a string
static bool Filter(string s) {
//return whether the string s contains the letter 'i'
//the Contains method will return a bool which we will return as well
return s.Contains("i") ;
}
Note how our method returns a bool and takes a string as a parameter.
So basically, we will return true if the string contains ‘i’. And the RemoveAll method will execute this Filter method on all the elements in our list.
Using Our Filters
So let’s now pass our Filter method to the RemoveAll method, and also let’s add a foreach loop before and after the RemoveAll method just for observation.
using System;
using System.Collections.Generic;
namespace DelegatesTestingGround {
class Program {
static void Main(string[] args) {
//list of names
List<string> names = new List<string>() { "Aiden", "Sif", "Walter", "Anatoli" };
Console.WriteLine("----before----");
//print the names before the remove all method
foreach(string name in names) {
Console.WriteLine(name);
}
//calling RemoveAll and passing a method Filter we created.
names.RemoveAll(Filter);
Console.WriteLine("----after----");
//print the names after the remove all method
foreach (string name in names) {
Console.WriteLine(name);
}
//pause
Console.ReadKey();
}
//a method called Filter that takes a string
static bool Filter(string s) {
//return whether the string s contains the letter 'i'
//the Contains method will return a bool which we will return as well
return s.Contains("i") ;
}
}
}