最近用C#做上位机程序开发,要实现这样一个功能:
父窗体创建了两个子窗体——子窗体1和子窗体2,子窗体1产生的数据要在子窗体2中显示出来。
因为这两个子窗体本身之间并没有直接关联,他们都是由父窗体new
出来的,所以就想着1的数据先发给父窗体,父窗体再发给2。这样结构上比较清晰,也符合松耦合的模式。结构如下:
窗体间数据传递的方法有多种,这里我们直接选择最被推荐的方法:委托(delegate
)和事件(event
)。
子窗体1发送消息给父窗体
在子窗体1中定义一个委托
代码语言:txt复制public delegate void SendMsg(string msg);
再定义一个事件
代码语言:txt复制public event SendMsg send;
点击发送按钮时,触发事件
代码语言:txt复制 private void button1_Click(object sender, EventArgs e)
{
send(textBox1.Text);
}
完整代码
代码语言:txt复制 public partial class Form_Child1 : Form
{
public delegate void SendMsg(string msg);
public event SendMsg send;
public Form_Child1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
send(textBox1.Text);
}
}
委托可以理解为方法的代理,当我需要调用方法时可以直接调用委托,而事件是绑定到委托上的。当事件被触发,就会运行我们最终想要执行的方法。
上面子窗体1已经注册好了委托和事件,接下来需要父窗体订阅该事件。
代码语言:txt复制 private Form_Child1 form_Child1;
public Form1()
{
InitializeComponent();
form_Child1 = new Form_Child1(); // 实例化子窗体1
form_Child1.send = new Form_Child1.SendMsg(receiveChild1Msg); // 订阅子窗体1的send事件
// 也可以简写成如下格式
// form_Child1.send = receiveChild1Msg;
}
其中receiveChild1Msg
是委托代理的方法,也就是要最终执行的方法,需要定义并实现
private void receiveChild1Msg(string msg)
{
transfer(msg); //此处写具体要做的事情
}
因为父窗体接收到子窗体1的消息后要转发给子窗体2,所以我们这里transfer(msg)
做的事情就是把信息再转发出去,具体见后面解析。
父窗体转发消息给子窗体2
这回等于是父窗体给子窗体发消息,所以我们在父窗体中定义委托和事件,然后让子窗体2去订阅,代码如下,我们先去掉关于窗体1的那部分以方便观察。
代码语言:txt复制 private Form_Child2 form_Child2;
public delegate void TransferMsg(string msg); // 定义转发消息的委托
public event TransferMsg transfer; // 定义事件
public Form1()
{
InitializeComponent();
form_Child2 = new Form_Child2(); // 实例化子窗体2
transfer = new TransferMsg(form_Child2.getMsg); // 子窗体2订阅transfer事件
// 也可以简写成如下格式
//transfer = form_Child2.getMsg;
}
所以上面父窗体接收到子窗体1消息后的那个transfer(msg)
就是为了触发transfer
事件。这时候transfer
事件被触发,子窗体2中的getMsg
就会被执行
public void getMsg(string str)
{
BeginInvoke(new MethodInvoker(delegate {
listBox2.Items.Add(str);
}));
}
信息就被接收到了,这样就完成了整个消息的传递过程。
效果: