We all have studied delegates in programming, especially in high-level languages. But often, it’s hard to understand if you are new to programming. So, I’ll be writing here some stuff on the use of delegates with a simple example. I’ll be more focused on the answer to “Why we need delegate” instead of “How to use delegates”.
These are the things we are going to discuss in this article.
- What a Delegate is
- Why we need delegates
- Life without delegates
- Some real-time examples where we use delegates.
What a Delegate is
A delegate is a reference to a function, just like the pointers that we use in C or C++, to reference a variable. In the same way, we use delegates to reference functions in programming.
Why we need a Delegate
Instead of discussing how to use delegates or what the syntax of delegates is, it’s more important to know why we need to use this concept.
Delegates save the address or reference of a function which means we can access to that function without knowing its name.
Let’s discuss this with a real-life example. Suppose you don’t know the name of a town and road in a city but you know its location on Google or Bing maps. Then, you can easily access that location without knowing its name and other stuff.
Getting started with a simple example
Long-running tasks in any application make the application or software irresponsive. So to keep the user updated about the running task and to keep the application responsive while working with the long-running tasks, we can use different types of loading bar options -
- Progress Bar
- Ring Bar Etc.
Let's discuss XAML Progress Bar in WPF apps.
XAML Progress Bar represents a control that indicates that an operation is ongoing. It looks like this.
![Delegates]()
XAML Progress Bar has 2 states
- Determinate ( for the tasks whose time of completion is known already )
- Indeterminate ( for a task whose time of completion is dynamic or not known )
Whenever we need to perform a lengthy task, we start it asynchronously and we want to issue a notification whenever the task completes.
Like in the below example, the long-running task is being performed in a background class which is actually known as “Business Logic” of the application and it’s not a code that lies behind UI. This literally means that upon the completion of the long-running task, it’s not easy to access a UI method in order to change the UI.
So, instead of accessing the UI method or Control from background class, we simply access that function using a delegate reference.
Open VisualStudio and make a blank WPF app.
![Delegates]()
Once you click OK, you'll see an empty application like this.
We need 3 controls to implement Progress Ring Control in this app.
- Button - to start a lengthy task
- Label 1 to show time, and Label 2 to show status
- Progress Bar
- Text block
Make a Grid and place these controls accordingly.
- <Window x:Class="ProgressBarUndefinedTimeWPF.MainWindow"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:local="clr-namespace:ProgressBarUndefinedTimeWPF"
- mc:Ignorable="d"
- Title="MainWindow" Height="350" Width="525">
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition></RowDefinition>
- <RowDefinition></RowDefinition>
- <RowDefinition></RowDefinition>
- <RowDefinition></RowDefinition>
- <RowDefinition></RowDefinition>
- </Grid.RowDefinitions>
-
- <Button Grid.Row="1" x:Name="btn_StartLengthyTask" Click="btn_StartLengthyTask_Click" Width="200" Height="30" >Start Lengthy Task</Button>
-
- <ProgressBar Grid.Row="2" x:Name="pb_LengthyTaskProgress" Margin="10,20" Value="10" ></ProgressBar>
-
- <TextBlock Grid.Row="3" x:Name="lbl_TaskStatus" >Status...</TextBlock>
-
- </Grid>
- </Window>
Now, we need to understand the model of programming known as Event Driven Model. Because we’ll start a background task and time of completion for that task is not known, whenever that task will complete the processing, it will call a function on UI thread to inform the user that the task has been completed. And that function reference will be passed to the background thread while calling to it as well.
So, in order to save a function reference, we use Delegates. That delegate will contain the reference of the UI function and it will be passed as parameter to the background worker function.
So, first of all, we’ll declare a delegate in our program.
Keep in mind that we declare delegate in namespace instead of class. And use them inside the classes.
![Delegates]()
Here is the code.
- public delegate void RefToFunction();
After this, we’ll need 2 functions.
- One method will be called on Response from the background method
- The other method will be used to simulate the long-running task. This method will take the first method’s reference as parameter.
Here is the first method.
- private void OnReponse()
- {
- lbl_TaskStatus.Text = "Task Completed";
- pb_LengthyTaskProgress.IsIndeterminate = false;
- pb_LengthyTaskProgress.Value = 100;
- }
And, here you go with the second method.
- private async Task PerformLengthyTaskAsync(RefToFunction toFunction)
- {
- for (int i = 0; i < 5; i++)
- {
- await Task.Delay(1000);
- }
- toFunction.Invoke();
- }
We’ll invoke the second method from code behind in the button click event.
- private void btn_StartLengthyTask_Click(object sender, RoutedEventArgs e)
- {
- lbl_TaskStatus.Text = "Task in progress...";
- pb_LengthyTaskProgress.IsIndeterminate = true;
- RefToFunction toFunction = new RefToFunction(OnReponse);
- PerformLengthyTaskAsync(toFunction);
- }
You need to use the following namespaces to work with Tasks.
using System.Threading.Tasks;
Build the project and run it. Once you click the button, Progress Bar will appear for 5 seconds. Once the task is completed, the second method will fire up the OnReponse Method. There, we can change the UI accordingly.