海鸥航迹

学习之笔记,好文之收集。

导航

在.NET中利用委托实现窗体间安全通信

 

对于窗体间简单的通信,采用VB6.0的方法就能满足我们的要求,但在一些架构设计复杂的应用中,这种方法就显得有点捉襟见肘了,同时该方法还有一个缺点,就是它仅仅对通过.NET窗体向导添加进去的窗体起作用,而对于自定义的窗体类型我们是无法添加到Forms对象集合中的。而且也和其它诸如构造函数传参等方法一样,会在窗体间大量互相引用各自的成员,造成了彼此之间存在着很大的耦合性,非常不利于窗体模块间的独立,这不符合良好软件设计模式的思想。
如果我们想在一个窗体中访问另一个窗体中自定义的成员,必须把该成员的可见性设置为Public或者通过属性公开,通过属性公开的话还说得过去,但如果把可见性设置成Public的,这样做就无可避免的破坏了类型封装性的原则,而这一做法也是我们在.NET下开发相当乐意做的,特别是对于初次接触.NET的开发人员,实现访问另一类型中成员的话最先想到的就是把该成员的可见性设置为Public,当然这样做算不上是错误,但把这一做法作为自己的首要灵感,至少从面向对象的角度出发显然是不合适的。
在.NET下,还为我们提供了另外一种强大的机制来实现窗体通信,这就是委托。委托可理解为一种类型安全的函数指针,.NET下的事件的实现都是以委托做为基础的。关于委托在这篇文章中我就不详细介绍了,后边会有文章专门介绍这一概念。 在此我演示通过在一个窗体里向另外一个窗体里的ListBox控件添加Item项来说明这一方法。因此需要两个窗体,一个MainFrm窗体,一个ChildFrm窗体,另外还需要一个Middle类,作为MainFrm和ChildFrm之间通信的桥梁。我给出C#语言的代码,大家可以参考一下。
首先是MainFrm窗体,在MainFrm窗体中,拖一个ListBox控件即可,MainFrm.cs的代码如下:
下面是对应的C#代码,MainFrm.cs:
public partial class MainFrm: Form
{
  private void MainFrm _Load(object sender, EventArgs e)
  {
    Middle.sendEvent += new Middle.SendMessage(this.DoMethod);
  }
  public void DoMethod(string getstr)
  {
    lsMain.Items.Add(getstr);
  }
}
ChildFrm.cs:
public partial class ChildFrm: Form
{
  public ChildFrm ()
  {
    InitializeComponent();
  }
  private void btnAdd_Click(object sender, EventArgs e)
  {
    Middle.DoSendMessage(this.textBox1.Text);
    txtItem.Text = "";
    txtItem.Focus();
  }
}
Middle.cs:
public static class Middle
{
  public delegate void SendMessage(string str);
  public static event SendMessage sendEvent;
  public static void DoSendMessage(string str)
  {
    sendEvent(str);
  }
}
同样我们修改一下Program.cs的代码:
static class Program
{
  [STAThread]
  static void Main()
  {
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    childFrm child = new childFrm();
    child.Show();
    Application.Run(new mainFrm());
  }
}
根据以上代码我们可以看出:C#则必须由我们自己首先声明事件的委托原型,然后再基于该委托声明事件,从这点看来VB.NET显得更简洁,其实VB.NET编译器在背后会自动的为我们定义一个委托对象,而且该委托与C#代码声明的委托所生成IL代码是一样的,这点大家可以通过Ildasm中间代码查看器来查看一下。引发事件,VB.NET是通过RaiseEvent关键字加上事件名称,而C#则是通过直接使用事件名称;最后是绑定事件的代码,VB.NET是通过AddHandler关键字,C#通过重载的+=操作符,对于以上两点,编译器同样会为我们生成一致的IL代码。
当然,上面的例子比较简单,不过我们完全可以通过委托实现复杂的窗体通信,比如可以传递复杂的数据类型,同时,可以在设计结构更加良好的中间通信类。但也要提醒大家,不要动不动就要用委托,它会增加程序的复杂性,应该根据自己的需求考虑用何种方法。

转:http://www.isabout.net/article.asp?id=215

posted on 2007-05-23 22:11  海天一鸥  阅读(844)  评论(0编辑  收藏  举报