C# 窗体间传值(综合版)

在写winform的过程中,我们经常遇到需要窗体间传值。今天在此总结一下,分享给各位。

窗体间传值有几种情况:

1、一个项目内(指的是在解决方案管理器中的同一个项目,如下图)

2、在另一个项目或类库中调用窗体的事件或方法,或改变窗体的某个状态,总之,你需要在另一个项目或类库中改变另一个窗体中的一些东西,而这两个不在同一个项目下,如下图:

3、在另一个项目中调用窗体中的方法,但与 2 不同的事,他们在不同的线程中,当前本例不会取消控件的安全检查。

=============================解决方法==============================================

下面介绍了本人认为的应对这三种情况最好的方法。

第一种情况很简单:以同一个项目中的一个类库 改变窗体中TextBox的值为例。

第一步 在这个项目中新建一个类库 Helper,添加一个公用的方法SetTextBox

其中 FormMain 为当前窗体的类型

第二步 在窗体中定义一个公共的方法,在这个方法内改变TextBox的值:

第三步 在窗体中增加一个按钮Button1,当按钮点击的时候调用类库中的方法改变窗体中TextBox的值

 全部代码:

 

View Code
 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 }

 

View Code
 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,此类专门用于存储委托(本人习惯,也可以放到其他类文件中,但不能包含在类中)

 
View Code
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本人已删除,避免重名后还要写命名空间)

 
View Code
 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 }

 

  

第四步:窗体中的方法,一共有两个,第一个是类库中调用的方法,第二个是要调用类库的方法

View Code
 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参数,无法调用窗体中的多个方法。

带着这些问题,请看实例三。

***************************************************************************************************************************************************

 

实例三: 在多线程中,类库调用窗体中的多个方法(改变多个控件的值或属性)

与实例二大同小异,由于代码上有注释,直接上代码了。

View Code
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; }
    }
}

 

View Code
 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 }

 

View Code
 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 }

 本人才疏学浅,在此分享思路为抛砖引玉,大家有不同的思路可以分享,让每个人都成为优秀的程序员。

如发现代码有问题,请回复。

 

 

posted @ 2012-12-04 00:17  易水寒2012  阅读(597)  评论(1编辑  收藏  举报