前几天讲到了子窗体给父窗体传值的问题,在此总结一下。这里就不讨论全局变量和静态变量之类的高耦合方式了,只讨论利用接口传父窗口指针和使用委托这两种耦合度相对较低的方式,具体怎么用看需求,没有哪个好哪个不好。
在这个例子中,我们有父窗体Form1和子窗体Form2,里面各有一个的文本框txt1和txt2,各有一个按钮。
一、接口法 首先要新建一个.cs文件写一个接口,内容如下:
1 public interface ITxt 2 { 3 void setTxt(string txt); 4 }
然后让主窗体Form1实现这个接口,
1 void ITxt.setTxt(string txt) 2 { 3 txt1.Text = txt; 4 }
点击主窗体按钮时:
1 private void button1_Click(object sender, EventArgs e) 2 { 3 Form2 frm = new Form2(this); 4 frm.ShowDialog(); 5 }
注意这里传进去的this就是主窗体本身,这就需要修改From2的构造函数了。 在Form2中,首先需要一个变量来保存传进来的Form1,也就是:
1 private ITxt itxt;
于是可以修改构造函数:
1 public Form2(ITxt itxt) 2 { 3 this.itxt = itxt; 4 InitializeComponent(); 5 }
当点击按钮时,调用传进来的Form1里面的setTxt函数:
1 private void button1_Click(object sender, EventArgs e) 2 { 3 string txt = txt2.Text; 4 itxt.setTxt(txt); 5 this.Close(); 6 }
调用Form2的构造函数时,传进来的是一个this,也就是Form1,但是并非是把整个Form1的实例都传进来了,而是传了一个“指针”。实质上Form2的构造函数接收的时一个ITxt型“接口变量”,可以理解成“ITxt itxt = new Form1();”,这是向上转换原则,类似的用法有在给抽象类对象new一个子类对象,通过itxt,只能点出Form1中的部分方法(接口里有的方法),并没有提高Form2对Form1内容的访问权限。
二、委托法 老样子,主窗体Form1里要有一个赋值的方法:
1 private void setTxt(string txt) 2 { 3 txt1.Text = txt; 4 }
之后要对子窗体Form2动手脚,先增加一个返回值和参数都对应的委托:
1 public delegate void DelSetTxt(string txt);
然后在窗体类内部声明一个委托变量
1 private DelSetTxt del;
在构造函数内赋值:
1 public Form2(DelSetTxt del) 2 { 3 this.del = del; 4 InitializeComponent(); 5 }
在Form1中,需要在new子窗体对象时把方法传进去(传到委托里):
1 private void button1_Click(object sender, EventArgs e) 2 { 3 Form2 frm = new Form2(setTxt); 4 frm.ShowDialog(); 5 }
这样一来只要在Form2的按钮点下时调用这个委托就可以了:
1 private void button1_Click(object sender, EventArgs e) 2 { 3 string txt = txt2.Text; 4 del(txt); 5 this.Close(); 6 }
这是委托的一个最典型的用处,Form2中del(txt);这句话就是一个“占位符”,执行的是Form1中的方法,委托就不多解释了。