NET, ASP.NET, AJAX, ASP.NET AJAX, JavaScript, WEB, WEB2.0, Neoking, Neoayi, Microsoft, SilverLight, CSS
代码改变世界

委托、事件和匿名方法

2007-10-28 06:54  黄明  阅读(181)  评论(0)    收藏  举报
在设计窗体程序时往往需要相互调用的窗体间传递复杂的数据,有时候甚至需要子窗体修改父窗体的内容。
有这么几种做法:
1)公开一个静态变量;
2)在子窗体中创建一个公有字段;
3)在父窗体中使用委托与事件;
4)将子窗体作为父窗体成员。

这些办法我感觉都不是特别好,会导致父窗体与子窗体耦合过于紧密,对任何一个窗体的修改需要重新编译另外一个窗体。根据“依赖倒置”的原则,通过引入一个结果对象,就可以避免这种紧耦合,同时也可以传递任意复杂的数据。如果需要在子窗体中改变父窗体状态,也可以在这个结果对象中定义委托与事件来达到目的。

相关的解决方案。
首先定义一个结果对象,用来存放子窗体返回的结果。同时定义一些事件,可以让子窗体修改父窗体的状态。代码如下:
using System;

namespace WinParam
{
   
public delegate void TextChangedHandler(string s);

   
public class cResult
   {
      
public string Result1 = "";
      
public string Result2 = "";
      
      
public event TextChangedHandler TextChanged;

      
public void ChangeText(string s)
      {
         
if(TextChanged != null)
            TextChanged(s);
      }
   }
}
添加一子窗体构造函数,允许接收一结果对象:
private cResult r;

public frmChild(cResult r):this()
{
   
this.r = r;            
}
在父窗体中创建子窗体,并订阅cResult事件:
private void btnCallChild_Click(object sender, System.EventArgs e)
{
   cResult r 
= new cResult();
   r.TextChanged 
+= new TextChangedHandler(this.EventResultChanged);
   frmChild fc 
= new frmChild(r);
   fc.ShowDialog();
   txtCallResult.Text 
= "The Result is: " + r.Result1 + " " + r.Result2;
}

private void EventResultChanged(string s)
{
   txtEventResult.Text 
= s;
}

这样确保父窗体知道子窗体,而子窗体不知道父窗体。父窗体改变后不需要重新编译子窗体。同时两个窗体都依赖于结果对象,结果对象的稳定性也决定了父窗体与子窗体关系的稳定性。下面是程序运行结果: