I\'m very new to c# and am trying my first experiments with 2 different forms.
I\'d like to make it so you have a label1 and a button1 on Form1, and a checkbox1 on F
Using a Controller and Events to decouple the forms
The correct way to do this kind of thing is to decouple the two forms from each other by introducing a Controller
class, and using events
to signal state changes.
Here's an example.
Firstly, create a new default Windows Forms app called WindowsFormsApplication1
and add two forms, form1
and form2
.
Then add to form1
a button called "button1" and a label called "label1".
Then add to form2
a checkbox called "checkbox1".
In the form1
designer, double-click the button to add a click handler for it.
In the form2
designer, double-click the checkbox to add a change handler for it.
Now add a new class called "Controller" and add to it the following code:
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
internal sealed class Controller
{
public void RunForm1()
{
_form1 = new Form1();
// The next line defines our response to the button being pressed in Form1
_form1.ButtonClicked += (sender, args) => showForm2();
Application.Run(_form1);
}
private void showForm2()
{
var form2 = new Form2();
// The next line defines our response to the checkbox changing in Form2.
form2.CheckBoxChanged +=
(sender, args) =>
_form1.SetLabel("Checkbox = " + ((CheckBox)sender).Checked);
form2.ShowDialog(_form1);
}
private Form1 _form1 ;
}
}
Now change Form1.cs
to this:
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1: Form
{
// Here's where we announce our event handler to the world:
public event EventHandler ButtonClicked;
public Form1()
{
InitializeComponent();
}
public void SetLabel(string text)
{
label1.Text = text;
}
private void button1_Click(object sender, EventArgs e)
{
// We make a copy of ButtonClicked before checking it for null because
// in a multithreaded environment some other thread could change it to null
// just after we checked it for nullness but before we call it, which would
// cause a null reference exception.
// A copy cannot be changed by another thread, so that's safe to use:
var handler = ButtonClicked;
if (handler != null)
handler(sender, e);
}
}
}
And change Form2.cs
to this:
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form2: Form
{
// Here's the event handler for the check box:
public event EventHandler CheckBoxChanged;
public Form2()
{
InitializeComponent();
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
var handler = CheckBoxChanged;
if (handler != null)
handler(sender, e);
}
}
}
Finally, change Program.cs
to this:
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Controller controller = new Controller();
controller.RunForm1();
}
}
}
Now run the program and click the button, then click the checkbox a few times. You will see the label in Form1 changing.
In this way, you have completely decoupled Form1
from Form2
and placed the control logic into a separate Controller class.
You can subscribe to the event CheckedChanged of the checkbox in the Form2 instance, directly from the Form1 instance. Inside Form1, just before displaying the Form2 subscribe to the CheckedChanged event of the checkbox
Form2 frm = new Form2();
frm.chkBox1.CheckedChanged += new EventHandler(this.ReceiveCheckedChanged);
frm2.ShowDialog();
and then define in Form1 (this) the handler for the checkedChanged event raised in Form2
private void ReceiveCheckedChanged(object sender, EventArgs e)
{
CheckBox chk = sender as CheckBox;
if(chk.Checked)
this.label1.Text = "Checked";
else
this.label1.Text = "UnChecked";
}
for this to work you need to change the property Modifiers
on the checkbox from Private
to Public
In this way your Form2 doesn't need to know that there is a Form1 and that every time someone clicks on the checkbox you need to change a label in another form. The responsability to change its internal state (the text on the label) is on Form1 who has notified the system of its requirements.
In this scenario you could use the CheckedChanged
event:
public void checkbox2_CheckedChanged(object sender, EventArgs e) {
if (checkbox2.Checked)
{
Form1.Label1.Text = "Checkbox 2 has been checked";
} else
{
Form1.Label1.Text = "";
}
}
http://www.c-sharpcorner.com/uploadfile/mahesh/checkbox-in-C-Sharp3/
Note you will have to change the Access Modifier in Form1
and make Label1
public so Form2
can alter the Text
property.
To do this, goto Form1
, select Label1
goto Properties
, select Modifiers
and change from Private
to Public
. Form2 will then have access to the Label
.
Form1:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var form = new Form2();
form.Changed += (o, args) => label1.Text = "some";
form.ShowDialog();
}
}
Form2:
public partial class Form2 : Form
{
public delegate void ChangedEventHandler(object sender, EventArgs e);
public event ChangedEventHandler Changed;
public Form2()
{
InitializeComponent();
}
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
if (Changed != null)
{
Changed(this, e);
}
}
}
Use CheckedChanged
event of CheckBox.
Also, you can review good tutorial how to use Events in C#.