4

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 Form2.

the button1 on Form1 opens Form2, and once you check checkbox1 on Form2, the text in label1 changes.

I'm thinking this has to be done using events, but events are the only thing up to now that genuinely confuse me, so I guess in essence this question is more about the usage of events. Which I also find terribly confusing if I look it up on MSDN and other websites.

Help would be very much appreciated, this is making me feel extremely stupid.

Nogard
  • 1,779
  • 2
  • 18
  • 21
Kevink
  • 65
  • 1
  • 5
  • 1
    They are one of the more complicated parts of C# (after Linq and Lambdas). Have you had a look at this MSDN page though? http://msdn.microsoft.com/en-us/library/aa645739%28v=vs.71%29.aspx Events are definitely the way to do this though. – Matthew Watson Mar 24 '13 at 23:06
  • 1
    Yes, you can easily do this. What have you tried? – Brian Mar 24 '13 at 23:07
  • In the last five months since I signed up on stackoverflow, this appears to be the most popular question in all of its forms for the C# tag, I have even answered few of them. – Nikola Davidovic Mar 24 '13 at 23:10

4 Answers4

2

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.

Darren
  • 68,902
  • 24
  • 138
  • 144
2

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.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
0

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#.

Daniil
  • 413
  • 3
  • 10
0

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.

Steve
  • 213,761
  • 22
  • 232
  • 286
  • Thanks a lot! if I understand correctly.. the eventhandler (in this case the custom made ReceiveCheckedChanged) is called (and thus it will be runned) every time CheckedChanged is called due to the checkbox being checked/unchecked? I don't really understand why frm.chkBox1.CheckedChanged += new EventHandler(this.ReceiveCheckedChanged); has to be before the showdialog, though? – Kevink Mar 24 '13 at 23:37
  • Because ShowDialog() is modal. When you enter in that code, you don't exit till the Form2 instance is closed. Therefore no way to subscribe and receive the event from the checkbox. – Steve Mar 24 '13 at 23:42