Pass value between forms using events
The correct way to inform another object that something has happened or a value has changed.
This comes up so many times in the Forums/Quick Answers I thought it was time for a Tip that I can point people to.
Passing a value from a child form to the parent is best achieved using an event. To a noob, creating events, especialy when passing a value, can seem unnecessarily complicated. The code below shows a simple implementation that can be adapted as required.
The example is using Forms, but the priciple applies to any object type.
All the code is commented, any questions - just ask!
// TextEventArgs.cs
using System;
public class TextEventArgs : EventArgs
{
// Private field exposed by the Text property
private string text;
public TextEventArgs(string text)
{
this.text = text;
}
// Read only property.
public string Text
{
get { return text; }
}
}
// Form2.cs
using System;
using System.Drawing;
using System.Windows.Forms;
public partial class Form2 : Form
{
// Our event
public event EventHandler<TextEventArgs> NewTextChanged;
/* Private field to hold the value that is passed around.
* Exposed by the NewText property and passed in the NewTextChanged event. */
private string newText;
/* The following line would normally be automatically created
* in the Form1.Designer.cs file. */
private TextBox textBox;
public Form2()
{
InitializeComponent();
/* The following lines would normally be automatically created
* in the Form2.Designer.cs file. */
textBox = new TextBox();
textBox.Location = new Point(92, 122);
textBox.TextChanged += new EventHandler(textBox_TextChanged);
Controls.Add(textBox);
}
// textBox.TextChanged handler
private void textBox_TextChanged(object sender, EventArgs e)
{
NewText = textBox.Text;
}
public string NewText
{
get { return newText; }
/* Setting this property will raise the event if the value is different.
* As this property has a public getter you can access it and raise the
* event from any reference to this class. in this example it is set from
* the textBox.TextChanged handler above. The setter can be marked as
* as private if required. */
set
{
if (newText != value)
{
newText = value;
OnNewTextChanged(new TextEventArgs(newText));
}
}
}
// Standard event raising pattern.
protected virtual void OnNewTextChanged(TextEventArgs e)
{
// Create a copy of the event to work with
EventHandler<TextEventArgs> eh = NewTextChanged;
/* If there are no subscribers, eh will be null so we need to check
* to avoid a NullReferenceException. */
if (eh != null)
eh(this, e);
}
}
// Form1.cs
using System;
using System.Drawing;
using System.Windows.Forms;
public partial class Form1 : Form
{
/* The following line would normally be automatically created
* in the Form1.Designer.cs file */
private Button buttonShowForm2;
public Form1()
{
InitializeComponent();
/* The following lines would normally be automatically created
* in the Form1.Designer.cs file */
buttonShowForm2 = new Button();
buttonShowForm2.Location = new Point(105, 121);
buttonShowForm2.Text = "Show Form2";
buttonShowForm2.Click += new EventHandler(buttonShowForm2_Click);
Controls.Add(buttonShowForm2);
}
private void buttonShowForm2_Click(object sender, EventArgs e)
{
Form2 form2 = new Form2();
// Subscribe to event
form2.NewTextChanged += new EventHandler<TextEventArgs>(form2_NewTextChanged);
form2.ShowDialog();
// Unsubscribe from event
form2.NewTextChanged -= form2_NewTextChanged;
form2.Dispose();
form2 = null;
}
// Our new event (form2.NewTextChanged) handler
private void form2_NewTextChanged(object sender, TextEventArgs e)
{
Text = e.Text;
}
}