应用程序开发中,经常需要多窗体之间进行数据通信,写几个例子,把几种常用的通信方式总结一下:

主窗体Form1是一个ListBox,单击选中某列时,弹出窗体Form2,Form2中两个控件,一个是TextBox,显示选中的该列的文本,另一个是按钮,点击时将修改后的值回传,且在Form1中修改相应的列的文本,同时Form2关闭。

方法一:传值

   最先想到的,Form2构造函数中接收一个string类型参数,即Form1中选中行的文本,将Form2的TextBox控件的Text设置为该string,即完成了Form1向Form2的传值。当Form2的AcceptChange按钮按下,需要修改Form1中ListBox中相应列的值,因此可以考虑同时将Form1中的ListBox控件当参数也传入Form2,所有修改工作都在Form2中完成,根据这个思路,Form2代码如下:
  1. publicpartial class Form2 : Form
  2. {
  3. private string text;
  4. private ListBox lb;
  5. private int index;
  6. //构造函数接收三个参数:选中行文本,ListBox控件,选中行索引
  7. public Form2(string text,ListBox lb,int index)
  8. {
  9. this.text = text;
  10. this.lb = lb;
  11. this.index = index;
  12. InitializeComponent();
  13. this.textBox1.Text = text;
  14. }
  15. private void btnChange_Click(object sender, EventArgs e)
  16. {
  17. string text = this.textBox1.Text;
  18. this.lb.Items.RemoveAt(index);
  19. this.lb.Items.Insert(index, text);
  20. this.Close();
  21. }
  22. }

Form1中new窗体2时这么写:

  1. public partial class Form1 :Form
  2. {
  3. int index = 0;
  4. string text = null;
  5. public Form1()
  6. {
  7. InitializeComponent();
  8. }
  9. private void listBox1_SelectedIndexChanged(object sender, EventArgse)
  10. {
  11. if (this.listBox1.SelectedItem != null)
  12. {
  13. text = this.listBox1.SelectedItem.ToString();
  14. index = this.listBox1.SelectedIndex;
  15. //构造Form2同时传递参数
  16. Form2 form2 = new Form2(text, listBox1, index);
  17. form2.ShowDialog();
  18. }
  19. }

OK,方法一的解决方法就是这样,好处是直观,需要什么就传什么,缺点也是显而易见的,如果窗体1中需要修改的是一百个控件,难道构造的时候还传100个参数进去?况且如果其他窗体仍然需要弹Form2,那Form2就废了,只能供窗体1使用,除非写重载的构造函数,不利于代码的复用,继续看下一个方法。

   方法二:继承
   这个方法我试了很多次,继承的确可以做,但是麻烦不说,还不方便,因此个人认为如果为了互相操作数据而使用继承,是不合适的,但既然是个方法,就扔出来看看,实际作用≈0。
   Form2:
  1. //声明Form2继承于Form1
  2. public partial classForm2 : Form1
  3. {
  4. publicint index;
  5. public ListBox lb;
  6. public Form2(string text)
  7. {
  8. //将继承过来的listBox设置为不可见
  9. this.listBox1.Visible=false;
  10. InitializeComponent();
  11. this.textBox1.Text = text;
  12. }
  13. private void btnChange_Click(object sender, EventArgs e)
  14. {
  15. string text = this.textBox1.Text;
  16. this.lb.Items.RemoveAt(index);
  17. this.lb.Items.Insert(index,text);
  18. this.Close();
  19. }
  20. }
Form1:
  1. public partial class Form1 :Form
  2. {
  3. public int index = 0;
  4. public string text = null;
  5. public Form1()
  6. {
  7. InitializeComponent();
  8. }
  9. private void listBox1_SelectedIndexChanged(object sender, EventArgse)
  10. {
  11. if (this.listBox1.SelectedItem != null)
  12. {
  13. text = this.listBox1.SelectedItem.ToString();
  14. index = this.listBox1.SelectedIndex;
  15. Form2 form2 = new Form2(text);
  16. //构造完Form2后,为Form2中各参数赋值
  17. form2.lb =this.listBox1;
  18. form2.index = index;
  19. form2.Show();
  20. }
  21. }
  22. }
 这里有几点问题需要注意,Form2中各属性需要哪种赋值方法?从Java过度来的都知道,Java继承中在子类中使用关键字super可以访问基类中公有的方法及参数,而C#中super换成了base,那是不是意味着我们可以在Form2中这么为参数赋值呢?
  1. this.lb=base.listBox1;
  2. this.index=base.index;

OK,第二种写法没问题,可以保存index值,但是对ListBox控件,这么赋值就会出问题,通过测试我发现,base.listBox1指向的,是子类继承过来的listBox1对象,并不是基类自己的listBox1对象。因此我们猜测,那base.index值是不是也是指向子类的index呢?测试一下发现的确是这样,因此this.index=base.index等于没写,去掉照样可以用,因为index一样被Form2继承过来了,因此我们可以了解到,C#中的窗体继承,通过base.控件是无法操作基类控件的。

   方法三:事件回调
   既然C#有事件这个东西,为啥不用呢,而且事件在窗体通信方面,有着更为方便的作用,我们知道事件实际上就是状态的捕获,在最后我会举一个捕获状态的例子,先看数据互相操作的例子。
   Form2:
  1. //定义一个需要string类型参数的委托
  2. publicdelegate void MyDelegate(string text);
  3. public partial class Form2 :Form1
  4. {
  5. //定义该委托的事件
  6. public event MyDelegate MyEvent;
  7. public Form2(string text)
  8. {
  9. InitializeComponent();
  10. this.textBox1.Text = text;
  11. }
  12. private void btnChange_Click(object sender, EventArgs e)
  13. {
  14. //触发事件,并将修改后的文本回传
  15. MyEvent(this.textBox1.Text);
  16. this.Close();
  17. }
  18. }
  Form1:
  1. public partial class Form1 :Form
  2. {
  3. public int index = 0;
  4. public string text = null;
  5. public Form1()
  6. {
  7. InitializeComponent();
  8. }
  9. private void listBox1_SelectedIndexChanged(object sender, EventArgse)
  10. {
  11. if (this.listBox1.SelectedItem != null)
  12. {
  13. text = this.listBox1.SelectedItem.ToString();
  14. index = this.listBox1.SelectedIndex;
  15. Form2 form2 = new Form2(text);
  16. //注册form2_MyEvent方法的MyEvent事件
  17. form2.MyEvent += new MyDelegate(form2_MyEvent);
  18. form2.Show();
  19. }
  20. }
  21. //处理
  22. void form2_MyEvent(string text)
  23. {
  24. this.listBox1.Items.RemoveAt(index);
  25. this.listBox1.Items.Insert(index, text);
  26. }
  27. }
可以看出,使用事件做是很方便的,并且不需要传递那么多参数,不需要有继承关系,且提高了代码重用,因此在一般的需求下,建议这么使用。

C#窗体间通讯的几种处理方法的更多相关文章

  1. 总结几种C#窗体间通讯的处理方法

    摘要:本文介绍了C#窗体间通讯的几种处理方法,即传值.继承.事件回调,希望对大家有用. http://www.cnblogs.com/jara/p/3439603.html 应用程序开发中,经常需要多 ...

  2. C#窗体间常用的几种传值方式、以及委托与事件的详细介绍

    窗体间的传值,最好使用委托方式传值,开始之前,我们先来说一下委托与事件的关系. 委托:是一个类. 事件:是委托类型的一个特殊实例,只能在类的内部触发执行. 首先创建2个窗体,这里我们以form1为发送 ...

  3. Linux进程间通讯的几种方式的特点和优缺点,和适用场合

    http://blog.csdn.net/jeffcjl/article/details/5523569 由于不同的进程运行在各自不同的内存空间中.一方对于变量的修改另一方是无法感知的.因此.进程之间 ...

  4. linux进程间通讯的几种方式的特点和优缺点

    # 管道( pipe ):管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用.进程的亲缘关系通常是指父子进程关系.# 有名管道 (named pipe) : 有名管道也是 ...

  5. Android线程间通讯的几种方式

    1.runOnUiThread(Runnable)              在子线程中直接使用该方法,可以更新UI runOnUiThread(new Runnable(){//更新UI       ...

  6. C#进程间通讯或同步的框架引荐

    这篇文章主要介绍了一个进程间通讯同步的C#框架,代码具有相当的稳定性和可维护性,随着.NET的开源也会被注入更多活力,推荐!需要的朋友可以参考下  0.背景简介 微软在 .NET 框架中提供了多种实用 ...

  7. C# winform窗体间传值(使用委托或事件)

    窗体间传值 今天得空,刚好看到网上好多人再找winform窗体间传值的问题,由于昨天项目的优化的感觉不错,就写了个C# winform窗体间传值的demo,希望能给需要的人的带来帮助: 工程的源代码地 ...

  8. C#利用事件与委托进行窗体间传值简单小例子

    本篇博客是利用C#委托与事件进行窗体间传值的简单小例子 委托与事件的详细解释大家可以参照张子阳的博客: http://www.tracefact.net/CSharp-Programming/Dele ...

  9. C#窗体间传值的简便方法/工具

    一.问题:窗体间传值必须需要窗体之间有联系,具体有如下方式 窗体间传值涉及到窗体A必须拥有窗体B,这样才可以实现A-B之间传值 窗体A与窗体B在窗体/实例C中,A-B可互相通讯 其他方式,不细讨论,复 ...

随机推荐

  1. Java Error和Exception区别

    Error和Exception都继承自Throwable: 二者不同之处: Exception: 1.可以是可被控制(checked)或者不可控制(unchecked): 2.表示一个由程序员导致的错 ...

  2. Hadoop集群中Hbase的介绍、安装、使用

    导读 HBase – Hadoop Database,是一个高可靠性.高性能.面向列.可伸缩的分布式存储系统,利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群. 一.Hbase ...

  3. cocos2d anchor point 锚点解析

    anchor point 究竟是怎么回事? 之所以造成不容易理解的是因为我们平时看待一个图片是 以图片的中心点 这一个维度来决定图片的位置的.而在cocos2d中决定一个 图片的位置是由两个维度 一个 ...

  4. 提高Web页面性能的技巧

    现在动辄几兆大小的页面加载量,让性能优化成了不可避免的热门话题.WEB 应用越流畅,用户体验就会越好,继而带来更多的访问量.这也就是说,我们应该反省一下那些过度美化的 CSS3 动画和多重操作的 DO ...

  5. CSS垂直水平完全居中手册

    水平居中 内联元素(inline or inline-*)居中? 你可以让他相对父级块级元素居中对齐 .center-children { text-align: center; } 块级元素(blo ...

  6. SOA和NS区别

    SOA是起始权威服务器,在该服务器上可以新增和删除记录; NS服务器是笔试哪些DNS服务器可以解析该域名; 对于一个域(如baidu.com)SOA只有一个NS可以有多个. NS服务器包含SOA,SO ...

  7. 关于ShareSDK接入的各种问题,以及解决方案

    随着社交网络的流行,游戏接入分享已经是必然.毕竟这是非常好的一种推广方式.ShareSDK是一个非常好的内分享提供商!但是接入后发生的各种问题,下面给大家提供几个本人遇到的问题,以及解决方法: 1)微 ...

  8. 用Windows Live Writer发来

    文字     package com.myeclipseide.example.myblog.secure; import com.opensymphony.xwork2.ActionSupport; ...

  9. The First Pig Task

                         The First Pig Program 环境: Hadoop-1.1.2 pig-0.11.1 linux系统为CentOS6.4 jdk1.6 在伪分布 ...

  10. Apache Spark GraphX的使用简介

    类似 Spark 在 RDD 上提供了一组基本操作符(如 map, f ilter, reduce), GraphX 同样也有针对 Graph 的基本操作符,用户可以在这些操作符传入自定义函数和通过修 ...