Winform笔记:窗体间相互访问的几种实现方法
程序员文章站
2022-05-06 08:05:06
...
窗体组合经常会使用到,但是要避免循环引用的问题。
窗体对象相互引用的可以使用单例模式,用窗体类静态方法获取实例对象再去调用具体内容。在窗体间相互引用时,使用单例可以解决循环引用问题。
窗体间的数据传递可以使用委托和事件
委托与事件的区别:个人乱扯
委托是类;事件是一种委托类型,提供发布和订阅机制。
委托由定义者注册和注销和执行;事件由定义者触发,提供调用者注册和注销
委托使用Func<> 和 Action<> 可以满足丰富的委托类型,注册委托的函数需要满足委托函数签名,可实现同步,异步且能带回调执行委托
事件直接用EventArgs,或EventArgs继承自定义事件类丰富事件属性;注册事件函数需要提过(object sender, MsgEventArgs e)参数
使用单例
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class Form2 : Form
{
//窗体组合经常会使用到,但是要避免循环引用的问题。
//窗体对象相互引用的可以使用单例模式,用窗体类静态方法获取实例对象再去调用具体内容。在窗体间相互引用时,使用单例可以解决循环引用问题。
public TextBox TextBox1
{
get
{
return this.textBox1;
}
set
{
this.textBox1 = value;
}
}
//在Form2中添加Form3实例引用,组合
private static readonly Form3 form3 = Form3.GetForm3();
//Form2实例单例
private static readonly Form2 form2 = new Form2();
private Form2()
{
InitializeComponent();
}
//获取Form2单例实例
public static Form2 GetForm2()
{
return form2;
}
private void Form2_Load(object sender, EventArgs e)
{
banding(form3, panel1);
}
private void banding(Form form, Panel panel)
{
panel.Controls.Clear();
form.FormBorderStyle = FormBorderStyle.None;
form.StartPosition = FormStartPosition.Manual;
//form.Size = page.Size;
form.Dock = DockStyle.Fill;
form.TopLevel = false;
panel.Controls.Add(form);
form.Show();
}
private void button1_Click(object sender, EventArgs e)
{
//在Form2中通过form3引用修改Form3内容
form3.TextBox1.Text = "123";
}
private void button2_Click(object sender, EventArgs e)
{
}
private void button3_Click(object sender, EventArgs e)
{
Form4 form4 = new Form4();
form4.Show();
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class Form3 : Form
{
public TextBox TextBox1
{
get
{
return this.textBox1;
}
set
{
this.textBox1 = value;
}
}
//Form3实例单例
private static readonly Form3 form3 = new Form3();
private Form3()
{
InitializeComponent();
}
public static Form3 GetForm3()
{
return form3;
}
private void button1_Click(object sender, EventArgs e)
{
//因为Form2已经组合了Form3,想要通过Form3中修改Form2内容,不应该在Form3中组合Form2,会导致循环引用
//应该在Form3中直接调用Form2获取对象引用的静态方法去调用具体内容
//在窗体间相互引用时,使用单例可以解决循环引用问题
Form2.GetForm2().TextBox1.Text = "456";
}
private void button2_Click(object sender, EventArgs e)
{
}
private void Form3_Load(object sender, EventArgs e)
{
}
}
}
使用委托和事件
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WindowsFormsApp2
{
public class MsgEventArgs : EventArgs//自定义事件类;无参数时可以直接用EventArgs
{
public string Msg { get; private set; }
public MsgEventArgs(string msg)
{
this.Msg = msg;
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
//窗体间的数据传递可以使用委托和事件
public partial class Form4 : Form
{
//定义委托
public Action<string> SendMsg { get; set; }
public Form4()
{
InitializeComponent();
}
private void Form4_Load(object sender, EventArgs e)
{
Form5 form5 = new Form5();
SendMsg += form5.SetText;//绑定委托;但委托被执行时,绑定委托的函数将被执行;可同步,异步且能带回调执行委托
form5.MsgInfoEvent += BingEvent;//订阅事件;但事件被触发时,订阅事件的函数将被调用
//委托与事件的区别:个人乱扯
//委托由定义者注册和注销和执行;事件由定义者触发,提供调用者注册和注销
//委托使用Func<> 和 Action<> 可以满足丰富的委托类型,注册委托的函数需要满足委托函数签名,可实现同步,异步且能带回调执行委托
//事件直接用EventArgs,或EventArgs继承自定义事件类丰富事件属性;注册事件函数需要提过(object sender, MsgEventArgs e)参数
banding(form5, panel1);
}
private void button1_Click(object sender, EventArgs e)
{
//执行委托
//if (SendMsg != null)
//{
// //执行委托,向form5传值
// SendMsg(this.textBox1.Text);
//}
//同步执行委托;阻塞
Debug.WriteLine("button1_Click begin");
//SendMsg.Invoke(this.textBox1.Text);
//异步执行委托;非阻塞
//需要在程序入口添加 Control.CheckForIllegalCrossThreadCalls = false; //设置不捕获线程异常
//解决“线程间操作无效: 从不是创建控件“xxxx”的线程访问它。”
//SendMsg.BeginInvoke(this.textBox1.Text,null,null);
SendMsg.BeginInvoke(this.textBox1.Text, Callback, null);//异步执行委托,委托函数执行完成后再执行回调函数Callback
Debug.WriteLine("button1_Click end");
}
//SendMsg回调函数
public void Callback(IAsyncResult iar)
{
//获取绑定委托函数的引用
AsyncResult ar = (AsyncResult)iar;
Action<string> del = (Action<string>)ar.AsyncDelegate;
del.EndInvoke(iar);//等待委托函数执行完成
Debug.WriteLine("Callback end");
}
//订阅事件函数
private void BingEvent(object sender, MsgEventArgs e)
{
this.textBox1.Text = e.Msg;
}
private void banding(Form form, Panel panel)
{
panel.Controls.Clear();
form.FormBorderStyle = FormBorderStyle.None;
form.StartPosition = FormStartPosition.Manual;
//form.Size = page.Size;
form.Dock = DockStyle.Fill;
form.TopLevel = false;
panel.Controls.Add(form);
form.Show();
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp2
{
public partial class Form5 : Form
{
public event EventHandler<MsgEventArgs> MsgInfoEvent;//类中声明事件;发布事件;提供外部订阅+=和注销-=
public Form5()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//触发事件,外部订阅事件的函数将被执行
EventHandler<MsgEventArgs> msgInfo = MsgInfoEvent;
if (msgInfo != null)
{
msgInfo(this, new MsgEventArgs(this.textBox1.Text));
}
}
public void SetText(string msg)
{
System.Threading.Thread.Sleep(3000);
this.textBox1.Text = msg;
}
}
}
上一篇: 39-jQuery显示和隐藏动画