当Form2中的复选框被勾选时,如何使Form1标签文本改变?

4

我刚接触c#,正在尝试使用两个不同的表单进行实验。

我想在Form1上添加一个label1和一个button1,在Form2上添加一个checkbox1。

当在Form1点击button1打开Form2,并勾选Form2中的checkbox1时,label1中的文本会发生变化。

我认为这需要使用事件来完成,但是到目前为止,事件是唯一真正让我感到困惑的东西,所以我想这个问题本质上更多地涉及了事件的使用。如果我在MSDN和其他网站上查找,我也会发现这非常困惑。

非常感谢您的帮助,这让我感到极度愚蠢。


1
它们是C#中较为复杂的部分之一(在Linq和Lambdas之后)。不过,你看过这个MSDN页面了吗?http://msdn.microsoft.com/en-us/library/aa645739%28v=vs.71%29.aspx 事件绝对是实现这一点的方法。 - Matthew Watson
1
是的,你可以很容易地做到这一点。你尝试过什么? - Brian
自从我在stackoverflow上注册以来的最后五个月中,这似乎是C#标签下所有形式中最受欢迎的问题,我甚至回答了其中的一些。 - Nikola Davidovic
4个回答

2
在这种情况下,您可以使用CheckedChanged事件:
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/

请注意,您需要更改Form1中的访问修饰符,并使Label1公共,以便Form2可以更改Text属性。

要做到这一点,请转到Form1,选择Label1,进入Properties,选择Modifiers并从Private更改为Public。然后,Form2将可以访问Label


1
你从哪里获取到变量Form1的? - Steve

2
使用控制器和事件来解耦表单
这种情况下正确的做法是通过引入一个“控制器”类并使用“事件”来信号状态变化,将两个表单相互解耦。
以下是一个示例。
首先,创建一个名为“WindowsFormsApplication1”的新默认Windows Forms应用程序,并添加两个表单,“form1”和“form2”。
然后在“form1”中添加一个名为“button1”的按钮和一个名为“label1”的标签。
然后在“form2”中添加一个名为“checkbox1”的复选框。
在“form1”设计器中,双击按钮以添加单击处理程序。
在“form2”设计器中,双击复选框以添加更改处理程序。
现在添加一个名为“Controller”的新类,并向其中添加以下代码:
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 ;
    }
}

现在将Form1.cs更改为以下内容:
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);
        }
    }
}

Form2.cs 改成这样:

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);
        }
    }
}

最后,请将Program.cs更改为以下内容:
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();
        }
    }
}

现在运行程序并单击按钮,然后点击复选框几次。您将看到Form1中的标签正在更改。
通过这种方式,您已经完全将Form1与Form2解耦,并将控制逻辑放置到一个单独的Controller类中。

0

表单1:

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();
    }
}

表单2:

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);
        }
    }
}

使用 CheckBox 的 CheckedChanged 事件。

另外,你可以查看一个好的 tutorial 如何在 C# 中使用事件。


0
您可以直接从Form1实例中订阅Form2实例中复选框的CheckedChanged事件。在显示Form2之前,在Form1中订阅复选框的CheckedChanged事件即可。
Form2 frm = new Form2();
frm.chkBox1.CheckedChanged += new EventHandler(this.ReceiveCheckedChanged);
frm2.ShowDialog();

然后在Form1中定义(this)处理Form2引发的checkedChanged事件的处理程序

private void ReceiveCheckedChanged(object sender, EventArgs e)
{
   CheckBox chk = sender as CheckBox;
   if(chk.Checked)
       this.label1.Text = "Checked";
   else
       this.label1.Text = "UnChecked";
}

为了使其工作,您需要将复选框上的 Modifiers 属性从 Private 更改为 Public

这样,您的 Form2 就不需要知道有一个 Form1,也不需要每次有人单击复选框时都需要更改另一个表单中的标签。更改其内部状态(标签上的文本)的责任在于 Form1,它已经通知系统其要求。


非常感谢!如果我理解正确的话..事件处理程序(在本例中为自定义的ReceiveCheckedChanged)会在每次由于复选框被选中/取消选中而调用CheckedChanged时被调用(因此它将被运行)?但我并不真正理解为什么frm.chkBox1.CheckedChanged += new EventHandler(this.ReceiveCheckedChanged);必须在showdialog之前呢? - Kevink
因为ShowDialog()是模态的。当你进入那段代码时,直到Form2实例关闭,你才能退出。因此无法订阅和接收复选框的事件。 - Steve

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接