Advertisement:

Skystone Software

http://www.SkystoneSoftware.com

.NET Programming

Using Delegates to Implement Callbacks
Published: 9/7/2005

Let's say that in your application you want Form2 to be able to communicate with Form1 as Form2 works on something. Let's take this further, and say that Form2 wants to be able to send messages back to whatever code created it, whether that is Form1 or something else. To do so, Form2 would declare some delegates that are accessible via external code (declared Public or Friend):

Public Class Form2 

	[...] 

	Public Delegate Sub PageDetailsChanged(ByVal CurPage As Integer, ByVal TotalPages As Integer) 

	[...] 

End Class 

At this point, your Delegate routine is just a signature for a routine that Form2 wants to be able to call at any given time. Think of Delegates as object representations of functions, sort of like a class that has one default function. Form2 contains this declaration because Form2 is the one calling it. Anyone who wants to be the recipient of this function call must create a routine that looks exactly like the Delegate declaration.

Let's say that in our example, Form1 is the form that instantiated Form2, and Form1 wants to be notified as Form2 does stuff. Form 1 would do this:

Public Class Form1 

	[...] 

	Private Sub Form2PageDetailsChanged(ByVal CurPage As Integer, ByVal TotalPages As Integer) 
		MessageBox.Show("Hey, the page details have changed!") 
	End Sub 

	[...] 

End Class

Form1 has now declared a routine that looks exactly like the Delegate declared on Form2. The name can be different, but the parameter signature (and return value, if any) has to match exactly.

Now on Form2 we will declare a public variable that is declared to be of the type of our previously-declared Delegate:

Public Class Form2 

	[...] 

	Public PageDetailChangedHandler As PageDetailsChanged 

	[...] 

End Class 

We have declared a public variable of type PageDetailsChanged, which refers back to the delegate declaration we made before. Now, Form1 can set this variable to refer to the routine that was declared on Form1 that exactly matches the delegate signature of PageDetailsChanged on Form2. Not to give away the whole story early, but this is going to enable Form2 to call our method on Form1 without having to have any prior knowledge of Form1 at all.

Public Class Form1 

	[...] 

	Dim clsForm2 As New Form2 
	clsForm2.PageDetailChangedHandler = New Form2.PageDetailsChanged(AddressOf Me.Form2PageDetailsChanged) 
	clsForm2.Show() 

	[...] 

End Class

So what we've done here is to set the public variable on Form2 (declared to be the type of our previously-declared delegate) to an instance of a new delegate pointing to the routine on Form 1 that just happens to match the signature of the previously-declared delegate on Form2. Also, Peter Piper picked a peck of pickled peppers.

Last step: add the code to Form2 that calls the delegate. Since we've designed our Form2 to not require any prior knowledge of who will be on the other end of this call (which is similar to the concept of raising events from a UserControl or a custom class), we have to check to make sure that the delegate variable has been set before we call it (because the calling code doesn't HAVE to implement this callback type procedure if it doesn't want to).

Public Class Form2 

	[...] 

	Dim iCurrentPage As Integer = 1 
	Dim iTotalPages As Integer = 500 
	If Not Me.PageDetailChangedHandler Is Nothing Then 
		Me.PageDetailChangedHandler(iCurrentPage, iTotalPages) 
	End If 

	[...] 

End Class 

And that's it, the proper use of Delegates to implement callback procedures. This may seem a bit convoluted, but it's an important concept to understand to ensure proper object oriented design. Understanding delegates it is also the first step towards implementing code in your application that works on one thread, and passes messages to UI elements in another thread.

This has been turned into a FAQ at VBCity.com, which you can view by clicking here.



Written by Scott Waletzko for Skystone Software.
Copyright 2005-2007 by Echosoft Design Studios, LLC, All Rights Reserved.