C# 窗体间传值(综合版)
在写winform的过程中,我们经常遇到需要窗体间传值。今天在此总结一下,分享给各位。
窗体间传值有几种情况:
1、一个项目内(指的是在解决方案管理器中的同一个项目,如下图)
2、在另一个项目或类库中调用窗体的事件或方法,或改变窗体的某个状态,总之,你需要在另一个项目或类库中改变另一个窗体中的一些东西,而这两个不在同一个项目下,如下图:
3、在另一个项目中调用窗体中的方法,但与 2 不同的事,他们在不同的线程中,当前本例不会取消控件的安全检查。
=============================解决方法==============================================
下面介绍了本人认为的应对这三种情况最好的方法。
第一种情况很简单:以同一个项目中的一个类库 改变窗体中TextBox的值为例。
第一步 在这个项目中新建一个类库 Helper,添加一个公用的方法SetTextBox
其中 FormMain 为当前窗体的类型
第二步 在窗体中定义一个公共的方法,在这个方法内改变TextBox的值:
第三步 在窗体中增加一个按钮Button1,当按钮点击的时候调用类库中的方法改变窗体中TextBox的值
全部代码:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Text; 7 using System.Windows.Forms; 8 9 namespace Win 10 { 11 public partial class FormMain : Form 12 { 13 14 public FormMain() 15 { 16 InitializeComponent(); 17 } 18 19 private void button1_Click(object sender, EventArgs e) 20 { 21 Helper h = new Helper(); 22 h.SetTextBox(this); 23 } 24 public void SetValue(string text) 25 { 26 this.textBox1.Text = text; 27 } 28 } 29 }
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 5 namespace Win 6 { 7 public class Helper 8 { 9 public void SetTextBox(FormMain f) 10 { 11 f.SetTextValue("通过类库改变窗体中TextBox的值"); 12 } 13 } 14 }
**********************************************************************************************************************************************
第二种情况
当遇到第二种情况是再用第一种情况已经不可以了,因为窗体肯定要引用类库,而类库不能引用窗体(否则会vs就会告诉你循环引用了,神马?循环引用都不知道?自己去找解释吧)
这时候就应该请出 委托 大神了。
本例还是模拟上一次操作,只不过是在类库中调用方法改变窗体中的某个值。
第一步,在窗体中引用类库。
第二部,在类库中增加一个类 DEL,此类专门用于存储委托(本人习惯,也可以放到其他类文件中,但不能包含在类中)
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 5 namespace Win.Lib 6 { 7 public delegate void DelSetTextValue(string text); 8 }
第三步:在类库中再增加一个类 Helper(第一个实例中的Helper本人已删除,避免重名后还要写命名空间)
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 5 namespace Win.Lib 6 { 7 public class Helper 8 { 9 public void SetFormTextValue(DelSetTextValue setValue) 10 { 11 setValue("在类库中调用窗体中的方法"); 12 } 13 } 14 }
第四步:窗体中的方法,一共有两个,第一个是类库中调用的方法,第二个是要调用类库的方法
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Text; 7 using System.Windows.Forms; 8 using Win.Lib; 9 10 namespace Win 11 { 12 public partial class FormMain : Form 13 { 14 public FormMain() 15 { 16 InitializeComponent(); 17 } 18 19 public void SetTextValue(string text) 20 { 21 this.textBox1.Text = text; 22 } 23 24 private void button1_Click(object sender, EventArgs e) 25 { 26 Helper h = new Helper(); 27 h.SetFormTextValue(SetTextValue); 28 } 29 } 30 }
至此,第二个实例完成。
但这个有个弊端,就是当使用多线程的时候,无法调用,原因有二:
一:多线程有对量安全性检查,非本线程创建的控件其它线程不能访问,当然你可以去掉控件的安全性检查,但这样会不安全。
二:由于多线程只能传一个object参数,无法调用窗体中的多个方法。
带着这些问题,请看实例三。
***************************************************************************************************************************************************
实例三: 在多线程中,类库调用窗体中的多个方法(改变多个控件的值或属性)
与实例二大同小异,由于代码上有注释,直接上代码了。
using System; using System.Collections.Generic; using System.Text; namespace Win.Lib { public delegate void DelSetTextValue(string text); public class ThreadModel { public DelSetTextValue SetLblValue { get; set; } public DelSetTextValue SetTextValue { get; set; } } }
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 5 namespace Win.Lib 6 { 7 public class Helper 8 { 9 public void ChangeFormValue(object obj) 10 { 11 //将obj拆箱为ThreadModel类型 12 ThreadModel tm = obj as ThreadModel; 13 tm.SetLblValue("异线程调用窗体中的方法_Lbl"); 14 tm.SetTextValue("异线程调用窗体中的方法_Text"); 15 } 16 } 17 }
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Text; 7 using System.Windows.Forms; 8 using System.Threading; 9 using Win.Lib; 10 11 namespace Win 12 { 13 public partial class FormMain : Form 14 { 15 16 public FormMain() 17 { 18 InitializeComponent(); 19 } 20 21 void SetTextValue(string text) 22 { 23 if (InvokeRequired) 24 { 25 Invoke(new DelSetTextValue(SetTextValue), text); 26 } 27 else 28 { 29 this.textBox1.Text = text; 30 } 31 } 32 33 void SetLblValue(string text) 34 { 35 if (InvokeRequired) 36 { 37 Invoke(new DelSetTextValue(SetLblValue),text); 38 } 39 else 40 { 41 this.label1.Text = text; 42 } 43 44 } 45 46 private void button1_Click(object sender, EventArgs e) 47 { 48 Helper h = new Helper(); 49 Thread t = new Thread(h.ChangeFormValue); 50 t.IsBackground = true; 51 52 //声明一个更新末班变量,并赋值 53 ThreadModel tm = new ThreadModel(); 54 tm.SetLblValue = SetLblValue; 55 tm.SetTextValue = SetTextValue; 56 57 //将tm封装为一个变量传给ChangeFormValue方法 58 t.Start(tm); 59 } 60 } 61 }
本人才疏学浅,在此分享思路为抛砖引玉,大家有不同的思路可以分享,让每个人都成为优秀的程序员。
如发现代码有问题,请回复。