Passing Data Between Forms – Using Delegates and Events

Broadcasting your data between forms using delegates and eventsBack in an article I wrote in 2010 titled “Passing Data Between Forms in C# or VB.NET“, I described one of a couple methods for passing data between two forms in a .NET forms project. One method was to publicly expose a method on a child form that the parent form could then call on when needed. At the same time I also mentioned, and advised against, using a public property. As with many things in programming, there is always more than one way to skin a cat. Ok, in programming there may be 10 ways to skin a cat, 5 of them inadvisable, 2 of them buggy, 1 so cryptic that it is impossible to use and that leaves us with only a couple “real” options. In this article I will discuss another way to pass data between forms… using delegates and events to notify other forms that something has happened.

What is a delegate?

I always found delegates to be a bit of a cryptic topic in that everywhere you go you find really vague or round-a-bout explanations of what they were. It wasn’t until I ran into an article in C++ about function pointers that it really clicked what delegates in .NET were, they are essentially pointers to functions! Only after awhile did I see that explanation pop up on MSDN for delegates. Way to go Microsoft on finally getting around to simplifying the explanation!

So to help you guys get the gist of it, just remind yourself that a delegate simply points at zero or more functions that match a specific signature. Thus when we call on a delegate, we are essentially calling zero or more functions at the same time.

If you think of this much like a radio or TV broadcaster, a delegate is like a station or channel. People can “subscribe” to that station or channel and anything broadcast out on that station or channel can be picked up by anyone listening to it.

What is an event?

Well events are a little simpler to understand. They are basically messages sent out to notify them that an action of some sort has happened. In our analogy of the radio or TV broadcaster, an event would be a signal to tell you that a show is starting or a signal to tell your PVR that it is time to start recording. Your PVR would listen for a “show is about to begin” event and choose whether or not to do anything in response to it.

Put this together with a delegate and an event notifies subscribers that something happened by calling on the delegate to tell them about it. In our project one form can setup a station or channel (a delegate), attach it to an event and let other forms subscribe or “listen” to that event. That way when we click a button or enter some text in a form control, we can notify other forms that the button was clicked and they can choose whether or not to respond.

Our Project Example

Ok so to demonstrate how ridiculously simple this is, we are going to setup a project which has two form classes in it. One is going to be our “parent” form that will spawn child forms, attach the child form’s method to an event (make them a subscriber) and notify them when we do something. This parent form will have two buttons. One to create a child form, the other to send an event which will be picked up by the children. Child forms will simply have a textbox to display the message when they hear the event. Each child could do whatever they want with the event from altering the message to not even choosing to do anything at all. Just because you listen doesn’t mean you need to act!

Let’s start with the code for our parent form…

public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
        }

        // Our delegate (which "points" at any method which takes an object and EventArgs)
        // Look familiar? This is the signature of most control events on a form
        public delegate void SendMessage(object obj,  EventArgs e);

        // Here is the event we trigger to send messages out to listeners
        public event SendMessage OnSendMessage;

        // When we click the message button, tell others to respond to our button being clicked
        private void SendMessageButton_Click(object sender, EventArgs e) {
            if (OnSendMessage != null) {
                OnSendMessage(this, e);
            }
        }

        // This event creates our second form, says "attach its MessageReceived function to the event"
        private void CreateChild_Click(object sender, EventArgs e) {
            Form2 child = new Form2();
            OnSendMessage += child.MessageReceived;
            child.Show();
        }
}

The four key pieces of information here are the creation of a delegate that defines the type of functions it can point at, the event which is of the delegate’s type, the calling of the event (giving it any parameters if required) and lastly attaching methods to the event so when the event is triggered it will call those functions.

In the code above you see our delegate points at functions which will return void and takes an object and EventArgs parameter. While this signature could be anything, our signature matches most control event methods (like button clicks etc). Next, we create our child forms one by one. See how we add “child.MessageReceived” to the event on line 23? This is saying that when the event is triggered by the button being clicked, call that function on the child form.

Let’s now take a look at a child form to see what happens there…

public partial class Form2 : Form {
        public Form2() {
            InitializeComponent();
        }

        public void MessageReceived(object sender, EventArgs e) {
            textBox1.Text = "Message received from form 1";
        }
}

Not a whole lot of action here as you can see. But when the child form receives a notice that the button on the parent was clicked, it will activate that MessageReceived event, receive two parameters (sender being the parent form… and yes that means you could ideally reach through that and access the parent form’s public data members) and set the textbox on the child form to our specific message. Pretty simple huh? Like I said when we call the event it will call all subscribers, one right after the other. This means you could spawn 20 child forms and they would all be subscribed to the same event.

You might be asking if you can add additional (perhaps custom) parameters to the event, add the additional parameter to the child’s MessageReceived and thus passing custom data through the parameter. The answer would be a resounding YES! This means you could pass a complex object, maybe with the state of every item on your parent form, to the child and have the child do whatever it wants with the data. Maybe the child needs to see the value of a progress bar on the parent. You could pass that value into a custom object, give it to child elements and if the child forms care, they will look at the progress value and activate controls on themselves.

This way of communication is “pushing” data out to child elements, but can you push from children back? Sure. Create a delegate and event on your children, use the “sender” parameter to subscribe the parent form to the event and trigger your own events to notify the parent.

I kept the example above as simple and bare bones as possible to show you all the required pieces and how they fundamentally fit together. The only thing left to explain is why we test the event for null before calling it. Well, remember when I was talking about “zero” or more listeners? Well there is the possibility that no one had subscribed to the event and in that case the event would be null meaning it isn’t pointing at any methods. So be sure to always check for this before triggering an event.

Conclusion

In the proceeding article we talked about a method to pass data from one form to another using delegates/events to “broadcast” actions to all the child forms who “subscribed” to the event. While this method is good for letting parent forms inform their children, we briefly talked about the idea of allowing the children to push notices back up to parent using the same technique. This process is good for a one-to-many situation and may be a little less useful in direct one-to-one form communication. I hope between this method and the ways I talked about in my previous article, you have all the answers you could ever want to describe how to get two forms to talk to one another. Thanks again for reading! 🙂

About The Author

Martyr2 is the founder of the Coders Lexicon and author of the new ebooks "The Programmers Idea Book" and "Diagnosing the Problem" . He has been a programmer for over 25 years. He works for a hot application development company in Vancouver Canada which service some of the biggest tech companies in the world. He has won numerous awards for his mentoring in software development and contributes regularly to several communities around the web. He is an expert in numerous languages including .NET, PHP, C/C++, Java and more.