Passing Data Between Windows Forms

Introduction

This article provides a simple example of using delegates and events to transfer data between Windows forms. The example provided contains three separate forms; the main form interacts with the other two forms by responding to events generated by instances of the other two forms.

In order to communicate between the forms, each of forms capable of generating an event contains declarations for a delegate and an event. A delegate may be thought of as a type safe function pointer and delegates are associated with methods that bear the same signature. An event is a device used to notify listening objects that something has happened; events are associated with a delegate when instantiated. 

Through the use of delegates and events it is possible to communicate values between forms in a Win Forms application.

PassingData1.gif

Figure 1. Using Delegates and Events to Communicate Between Forms 

Getting Started.

There is a single solution included with this download, the solution contains a Win Forms project called "PassBetweenForms"; this project contains three forms, one main form that creates instances of the other two forms and responds to events raised by the instances of those two forms. 

For the sake of an example, the main form (frmMain) contains an area used to contain an identity (first, middle, and last name) and an area used to display an address (street, city, state, and zip code). The values for these areas are displayed on the form but the form does not allow the user to enter the text directly into the form. 

In order to set the values associated with the ID or Address sections of the main form, the user must click on a "Set" button which creates an instance of either the "frmID" form or the "frmAddress" form. When data is entered into and submitted from either of these forms, the main form listens for an update event and then loads the information from either of the other two forms into the main form's associated text boxes.

PassingData2.gif
Figure 2. Solution Explorer 

Code:  The Address Form.

Rather than starting with the main form, first take a look at the Address form. The Address form contains three parts that make communication with the main form possible. Those parts are the delegate and event declarations and the declaration of a class used to define the content of the event arguments made available to the event listener when the event is fired.

The class declaration contains only the default imports and after the imports, the delegate and event are declared: 

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

 

namespace PassBetweenForms

{

    public partial class frmAddress : Form

    {

        // add a delegate

        public delegate void AddressUpdateHandler(object sender,

        AddressUpdateEventArgs e);

 

        // add an event of the delegate type

        public event AddressUpdateHandler AddressUpdated;

 

 

        public frmAddress()

        {

            InitializeComponent();

        } 

The signature of the delegate is pretty standard in this example, it contains the sender as an object and the event arguments; it is possible to use different signatures and return types, the approach used here is just a convenient way to return several values when an event is raised. The "AddressUpdateEventArgs" is the class used to provide a customized argument list to the project. This class inherits from the "EventArgs" class and contains properties used to capture the values provided on the form and to make them available to the listener when the event is fired.

The next bit of code in this class is used to handle the OK button's click event. When the OK button is clicked from this form, all of the text box values contained in the form are passed to string variables. Once the value have been collected, the custom event argument class is instantiated and, through its constructor, passed each of the values captured from the form. The address updated event is then fired and the event arguments are passed on to the listeners with the event; once the event is raised, the form is closed by calling the dispose method:

private void btnOkay_Click(object sender, EventArgs e)

{

    // this button click event handler will raise the

    // event which can then intercepted by any listeners

    // read the textboxes and set the member variables

    string sNewStreet = txtStreet.Text;

    string sNewCity = txtCity.Text;

    string sNewState = txtState.Text;

    string sNewZipCode = txtZipCode.Text; 

    // instance the event args and pass it each value

    AddressUpdateEventArgs args = new AddressUpdateEventArgs(sNewStreet,

    sNewCity, sNewState, sNewZipCode); 

    // raise the event with the updated arguments

    AddressUpdated(this, args); 

    this.Dispose();

}

The second class contained in the code file is the "AddressUpdateEventArgs" class. This class is pretty straight forward; it contains a set of local member variables used to capture the address information collected from the form and some public read only properties used to access those values. The class constructor accepts all of the arguments necessary to populate the event argument properties. The code is as follows:

public class AddressUpdateEventArgs : System.EventArgs

{

    // add local member variables to hold text

    private string mStreet;

    private string mCity;

    private string mState;

    private string mZipCode;

 

    // class constructor

    public AddressUpdateEventArgs(string sStreet, string sCity, string sState, string sZip)

    {

        this.mStreet = sStreet;

        this.mCity = sCity;

        this.mState = sState;

        this.mZipCode = sZip;

    }

 

    // Properties - Viewable by each listener 

    public string Street

    {

        get

        {

            return mStreet;

        }

    }

 

    public string City

    {

        get

        {

            return mCity;

        }

    }

 

    public string State

    {

        get

        {

            return mState;

        }

    }

 

    public string ZipCode

    {

        get

        {

            return mZipCode;

        }

    }

} 

Code:  The ID Form.

I am not going to describe the ID form as it is essentially the same as the Address form with the only exception being that it is used to capture the ID related information instead of the address information. The code for the ID form class is as follows:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

 

namespace PassBetweenForms

{

    public partial class frmID : Form

    { 

        // add a delegate

        public delegate void IdentityUpdateHandler(object sender,

        IdentityUpdateEventArgs e);

 

        // add an event of the delegate type

        public event IdentityUpdateHandler IdentityUpdated;

 

 

        // default constructor

        public frmID()

        {

            InitializeComponent();

        }

 

        // close the form without raising the event

        private void btnCancel_Click(object sender, EventArgs e)

        {

            this.Dispose();

        }

 

        // raise the event

        private void btnOkay_Click(object sender, EventArgs e)

        {

            // this button click event handler will raise the

            // event which can then intercepted by any listeners 

            // read the textboxes and set the variables

            string sNewFirst = txtFirstName.Text;

            string sNewMiddle = txtMiddleName.Text;

            string sNewLast = txtLastName.Text; 

            // instance the event args and pass it each value

            IdentityUpdateEventArgs args = new IdentityUpdateEventArgs(sNewFirst, sNewMiddle, sNewLast); 

            // raise the event with the updated arguments

            IdentityUpdated(this, args); 

            this.Dispose();

        }

    } 

 

    public class IdentityUpdateEventArgs : System.EventArgs

    {

        // add local member variable to hold text

        private string mFirstName;

        private string mMiddleName;

        private string mLastName;

 

        // class constructor

        public IdentityUpdateEventArgs(string sFirstName, string sMiddleName, string

        sLastName)

        {

            this.mFirstName = sFirstName;

            this.mMiddleName = sMiddleName;

            this.mLastName = sLastName;

        }

 

        // Properties - Accessible by the listener 

        public string FirstName

        {

            get

            {

                return mFirstName;

            }

        }

 

        public string MiddleName

        {

            get

            {

                return mMiddleName;

            }

        } 

 

        public string LastName

        {

            get

            {

                return mLastName;

            }

        }

    }

} 

Code:  Main Form.

The main form of the application is used to display the information originating from the ID and Address forms. The form contains a set of ID and a set of Address related text boxes that cannot be edited directly from the form. The form contains two buttons used to open an instance of either the Address or ID forms; information entered into those two forms is made available to the main form when the update event is fired from either of those forms.

The class is initialized with all of the default settings in terms of class library imports; the first part of the code is as follows:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

 

namespace PassBetweenForms

{

    public partial class frmMain : Form

    {

        // default constructor

        public frmMain()

        {

            InitializeComponent();

        }

 

        private void frmMain_Load(object sender, EventArgs e)

        {

            // nothing to do

        }

The first interesting bit of code in the main form is the button click event handler used to respond to a request to set the identity information; that code is as follows:

private void btnSetName_Click(object sender, EventArgs e)

{

    frmID f = new frmID();

    // Add an event handler to update this form

    // when the ID form is updated (when IdentityUpdated fires).

    f.IdentityUpdated += new

    frmID.IdentityUpdateHandler(IdForm_ButtonClicked);

    f.Show();

}

In this bit of code, a new instance of the ID form is created.  Next, the event used to notify the listener that the ID information has been updated is associated with event handler contained in this, the main form class. After this association is defined, the form is displayed.

The main form event handler associated with the ID form event is as follows:

// handles the event from frmId

private void IdForm_ButtonClicked(object sender, IdentityUpdateEventArgs e)

{

    // update the forms values from the event args

    txtFirstName.Text = e.FirstName;

    txtMiddleName.Text = e.MiddleName;

    txtLastName.Text = e.LastName;

}

This handler accepts the custom event argument list passed when the event is raised and the values contained in the event arguments are used to update the form's fields in response the event.

The next blocks of code are used to perform the same functions as the last two handlers only for the address information instead of the ID information:

private void btnSetAddress_Click(object sender, EventArgs e)

{

    frmAddress f = new frmAddress();

    // Add an event handler to update this form

    // when the Address form is updated (when AddressUpdated fires).

    f.AddressUpdated += new

    frmAddress.AddressUpdateHandler(AddressForm_ButtonClicked);

    f.Show();

}

 

// handles the event from frmAddress

private void AddressForm_ButtonClicked(object sender, AddressUpdateEventArgs e)

{

    // update the forms values from the event args

    txtStreet.Text = e.Street;

    txtCity.Text = e.City;

    txtState.Text = e.State;

    txtZipCode.Text = e.ZipCode;

}

The last bit of code is merely a click event handler for the exit button:

private void btnExit_Click(object sender, EventArgs e)

{

    Application.Exit();

}

That concludes the description of all of the code used in this example.

Summary.

The article shows one approach to using events and delegates to pass data between forms through the use of custom event arguments. There are other ways to perform the same tasks but this is a convenient  and easy approach to use. Delegates may be defined with different signatures and return types  and for that reason is it possible to devise a number of alternative approaches to passing data between forms.

This example showed how the approach can be used to pass multiple values between forms simultaneously, however, one could use the same approach to pass a single value or values of different types just as easily.