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

在进行C#应用程序开发的过程中,经常需要多窗体之间进行数据通信,本文举几个例子,把几种常用的通信方式总结一下,窗体界面如下图所示:

主窗体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代码如下:

publicpartial class Form2 : Form
{
    private string text;
    private ListBox lb;
    private int index; 

    //构造函数接收三个参数:选中行文本,ListBox控件,选中行索引
    public Form2(string text,ListBox lb,int index)
    {
      this.text = text;
      this.lb = lb;
      this.index = index;
      InitializeComponent();
      this.textBox1.Text = text;
    } 

    private void btnChange_Click(object sender, EventArgs e)
    {       

      string text = this.textBox1.Text;
      this.lb.Items.RemoveAt(index);
      this.lb.Items.Insert(index, text);
      this.Close();
    }
}

Form1中new窗体2时这么写:

public partial class Form1 :Form
{
    int index = 0;
    string text = null;
    public Form1()
    {
      InitializeComponent();
    } 

    private void listBox1_SelectedIndexChanged(object sender, EventArgse)
    {
      if (this.listBox1.SelectedItem != null)
      {
        text = this.listBox1.SelectedItem.ToString();
        index = this.listBox1.SelectedIndex; 

        //构造Form2同时传递参数
        Form2 form2 = new Form2(text, listBox1, index);
        form2.ShowDialog();
      }
    }
}

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

方法二:继承

这个方法我试了很多次,继承的确可以做,但是麻烦不说,还不方便,因此个人认为如果为了互相操作数据而使用继承,是不合适的,但既然是个方法,就扔出来看看,实际作用≈0。

Form2窗体:

//声明Form2继承于Form1 

public partial classForm2 : Form1
{
     publicint index; 

    public ListBox lb;
    public Form2(string text)
    {  

      //将继承过来的listBox设置为不可见 

      this.listBox1.Visible=false;
      InitializeComponent();
      this.textBox1.Text = text;
    }
    private void btnChange_Click(object sender, EventArgs e)
    {
      string text = this.textBox1.Text;
      this.lb.Items.RemoveAt(index);
      this.lb.Items.Insert(index,text);
      this.Close(); 

    }
}

Form1窗体:

public partial class Form1 :Form
{
    public int index = 0;
    public string text = null;
    public Form1()
    {
      InitializeComponent();
    } 

    private void listBox1_SelectedIndexChanged(object sender, EventArgse)
    {
      if (this.listBox1.SelectedItem != null)
      {
        text = this.listBox1.SelectedItem.ToString();
        index = this.listBox1.SelectedIndex;
        Form2 form2 = new Form2(text); 

        //构造完Form2后,为Form2中各参数赋值
        form2.lb =this.listBox1;
        form2.index = index;
        form2.Show();
      }
    }
}

这里有几点问题需要注意,Form2中各属性需要哪种赋值方法?从Java过度来的都知道,Java继承中在子类中使用关键字super可以访问基类中公有的方法及参数,而C#中super换成了base,那是不是意味着我们可以在Form2中这么为参数赋值呢?

this.lb=base.listBox1; 

this.index=base.index; 

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

方法三:事件回调

既然C#有事件这个东西,为啥不用呢,而且事件在窗体通信方面,有着更为方便的作用,我们知道事件实际上就是状态的捕获,在最后我会举一个捕获状态的例子,先看数据互相操作的例子。

Form2窗体:

//定义一个需要string类型参数的委托
publicdelegate void MyDelegate(string text);
public partial class Form2 :Form1
{
    //定义该委托的事件
    public event MyDelegate MyEvent;
    public Form2(string text)
    {
      InitializeComponent();
      this.textBox1.Text = text;
    }
    private void btnChange_Click(object sender, EventArgs e)
    { 

      //触发事件,并将修改后的文本回传
      MyEvent(this.textBox1.Text);
      this.Close();
    }
}

Form1窗体:

public partial class Form1 :Form
{
    public int index = 0;
    public string text = null;
    public Form1()
    {
      InitializeComponent();
    } 

    private void listBox1_SelectedIndexChanged(object sender, EventArgse)
    {
      if (this.listBox1.SelectedItem != null)
      {
        text = this.listBox1.SelectedItem.ToString();
        index = this.listBox1.SelectedIndex;
        Form2 form2 = new Form2(text); 

        //注册form2_MyEvent方法的MyEvent事件
        form2.MyEvent += new MyDelegate(form2_MyEvent);
        form2.Show();
      }
    } 

    //处理 

    void form2_MyEvent(string text)
    {
      this.listBox1.Items.RemoveAt(index);
      this.listBox1.Items.Insert(index, text);
    }
}

可以看出,使用事件确实是很方便的,并且不需要传递那么多参数,不需要有继承关系,且提高了代码重用,因此在一般的需求下,建议这么使用。

(0)

相关推荐

  • 利用thrift实现js与C#通讯的实例代码

    1.为什么要用thrift js C#? 1.1 首先,js 通过 thrift 访问C#,实际上是一种c/s模式.thrift是通信工具,js是客户端,C#是服务端. 1.2 使用js直接与thrift server通信.让web开发变得更简单.如果使用Web Service,你需要自己去实现C/S两端的序列化与反序列化操作,还需要自行处理异常,降低了开发效率.而thrift则会自动生成两端的操作类,你只需要处理方法内部的逻辑即可. 1.3 js直接与thrift server通信,可以提高性

  • 一个进程间通讯同步的C#框架引荐

     0.背景简介 微软在 .NET 框架中提供了多种实用的线程同步手段,其中包括 monitor 类及 reader-writer锁.但跨进程的同步方法还是非常欠缺.另外,目前也没有方便的线程间及进程间传递消息的方法.例如C/S和SOA,又或者生产者/消费者模式中就常常需要传递消息.为此我编写了一个独立完整的框架,实现了跨线程和跨进程的同步和通讯.这框架内包含了信号量,信箱,内存映射文件,阻塞通道,及简单消息流控制器等组件.这篇文章里提到的类同属于一个开源的库项目(BSD许可),你可以从这里下载到

  • 使用C#开发Socket通讯的方法

    下面的示例显示如何使用 Socket 类向 HTTP 服务器发送数据和接收响应. [C#]  public string DoSocketGet(string server)  {  //Sets up variables and a string to write to the server  Encoding ASCII = Encoding.ASCII;  string Get = "GET / HTTP/1.1\r\nHost: " + server +  "\r\n

  • C#程序窗体间使用回调事件方式通讯示例

    Form2: 复制代码 代码如下: //定义一个需要string类型参数的委托         publicdelegate void MyDelegate(string text);         public partial class Form2 :Form1         {                //定义该委托的事件             public event MyDelegate MyEvent;             public Form2(string te

  • ActiveMQ在C#中的应用示例分析

    本文实例讲述了ActiveMQ在C#中的应用.分享给大家供大家参考,具体如下: ActiveMQ是个好东东,不必多说.ActiveMQ提供多种语言支持,如Java, C, C++, C#, Ruby, Perl, Python, PHP等.由于我在windows下开发GUI,比较关心C++和C#,其中C#的ActiveMQ很简单,Apache提供NMS(.Net Messaging Service)支持.Net开发,只需如下几个步骤即能建立简单的实现.C++的应用相对麻烦些,后面会有文章介绍.

  • C#用Activex实现Web客户端读取RFID功能的代码

    由于要在Web项目中采用RFID读取功能,所以有必要开发Activex,一般情况下开发Activex都采用VC,VB等,但对这两块不是很熟悉,所以采用C#编写Activex的方式实现. 本文方法参考网络 1.编写WindowsFromControls 2.发布WindowsFormControls为Activex 3.在web中使用该Activex 首先编写windows控件 如何编写不再详述(注意一个地方,GUID自己用vs工具生成一个,下面会用到.我的0CBD6597-3953-4B88-8

  • C#实现同Active MQ通讯的方法

    本文实例讲述了C#实现同Active MQ通讯的方法.分享给大家供大家参考,具体如下: 内容概要: 主要以源码的形式介绍如何用C#实现同Active MQ 的通讯.本文假设你已经正确安装JDK1.6.x,了解Active MQ并有一定的编程基础. 正文: JMS 程序的最终目的是生产和消费的消息能被其他程序使用,JMS 的 Message 是一个既简单又不乏灵活性的基本格式,允许创建不同平台上符合非JMS 程序格式的消息. Message 由消息头,属性和消息体三部份组成. Active MQ支

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

    最近做项目遇到导出Excel的问题总结一下:看代码: 复制代码 代码如下: /// <summary>        /// 生成Excel的方法        /// </summary>        /// <param name="ds">DataSet</param>        /// <param name="url">Excel存在服务器的相对地址</param>       

  • C#编写ActiveX网页截图控件

    故事背景:Java组的小伙伴需要一个能在IE(还是6...)下截图并返回给网页的功能,但是IE做起来很麻烦(可能根本做不到),于是找到我写一个ActiveX控件实现此功能,想着可能还有其他小伙伴需要这个功能,于是就PO出来,供需要的人使用,当然也可以作为学习C#编写ActiveX的一个简单入门教程(VC++效果更好). 功能截图如下: 代码分为两个核心部分:1.C#屏幕截图:2.C#开发ActivX控件.  1.屏幕截图,这个在网上找到了一个只需要5行代码的实现(超级精简),当然你也可以费点功夫

  • C#窗体间通讯的几种常用处理方法总结

    在进行C#应用程序开发的过程中,经常需要多窗体之间进行数据通信,本文举几个例子,把几种常用的通信方式总结一下,窗体界面如下图所示: 主窗体Form1是一个ListBox,单击选中某列时,弹出窗体Form2,Form2中两个控件,一个是TextBox,显示选中的该列的文本,另一个是按钮,点击时将修改后的值回传,且在Form1中修改相应的列的文本,同时Form2关闭. 方法一:传值 最先想到的,Form2构造函数中接收一个string类型参数,即Form1中选中行的文本,将Form2的TextBox

  • Python实现8种常用抽样方法

    今天来和大家聊聊抽样的几种常用方法,以及在Python中是如何实现的. 抽样是统计学.机器学习中非常重要,也是经常用到的方法,因为大多时候使用全量数据是不现实的,或者根本无法取到.所以我们需要抽样,比如在推断性统计中,我们会经常通过采样的样本数据来推断估计总体的样本. 上面所说的都是以概率为基础的,实际上还有一类非概率的抽样方法,因此总体上归纳为两大种类: 概率抽样:根据概率理论选择样本,每个样本有相同的概率被选中. 非概率抽样:根据非随机的标准选择样本,并不是每个样本都有机会被选中. 概率抽样

  • WinForm中窗体间的数据传递交互的一些方法

    实际上过去我也写过类似的主题,这里把各种方法总结一下,内容的确基础了一些,所以这篇文章是写给刚刚学习C#的同行们的,希望对大家有些帮助吧!很抱歉,这篇文章没有诡异的bug来勾起大家的兴趣,但是下篇文章我会努力写些有趣的主题的! 在窗体间传递数据的方法比较多: 1,在子窗体中自定义一个构造函数,参数类型是主窗体,当要显示子窗体的时候,就用这个构造函数来实例化子窗体,然后把this指针传进去,说起来太抽象了,我大概一写大家应该就明白了: 复制代码 代码如下: public class frmMain

  • js跨域请求数据的3种常用的方法

    由于js同源策略的影响,当在某一域名下请求其他域名,或者同一域名,不同端口下的url时,就会变成不被允许的跨域请求. 那这个时候通常怎么解决呢,对此菜鸟光头我稍作了整理: 1.JavaScript    在原生js(没有jQuery和ajax支持)的情况下,通常客户端代码是这样的(我假设是在localhost:8080的端口下的http://localhost:8080/webs/i.mediapower.mobi/wutao/index.html页面的body标签下面加入以下代码): <scr

  • R语言中的五种常用统计分析方法

    1.分组分析aggregation 根据分组字段,将分析对象划分为不同的部分,以进行对比分析各组之间差异性的一种分析方法. 常用统计指标: 计数 length 求和 sum 平均值 mean 标准差 var 方差 sd 分组统计函数 aggregate(分组表达式,data=需要分组的数据框,function=统计函数) 参数说明 formula:分组表达式,格式:统计列~分组列1+分组列2+... data=需要分组的数据框 function:统计函数 aggregate(name ~ cla

  • 总结Linux 6种日志查看方法

    作为一名后端程序员,和Linux打交道的地方很多,不会看Linux日志,非常容易受到来自同事和面试官的嘲讽,所以掌握一种或者几种查看日志的方法非常重要. Linux查看日志的命令有多种: tail.cat.tac.head.echo等,本文只介绍几种常用的方法. 1.tail 这个是我最常用的一种查看方式 命令格式: tail[必要参数][选择参数][文件] -f 循环读取 -q 不显示处理信息 -v 显示详细的处理信息 -c<数目> 显示的字节数 -n<行数> 显示行数 -q,

  • C#窗体间常用的几种传值方式及委托与事件详解

    前言 窗体间的传值,最好使用委托方式传值,开始之前,我们先来说一下委托与事件的关系. 委托:是一个类. 事件:是委托类型的一个特殊实例,只能在类的内部触发执行. 首先创建2个窗体,这里我们以form1为发送窗体,form2为接收窗体 form1窗体 form2窗体 方式一(最简单的方式) form1窗体代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data;

  • 八种Vue组件间通讯方式合集(推荐)

    前言 Vue 提供了各种各样的通讯,其中包括 兄弟间 的通讯和 非兄弟间 的通讯,借此机会做个总结,查阅起来方便.如果喜欢的话可以帮忙点个赞 :+1: 或者关注一下 :yum: 1.props 目录结构 components ├── Parent.vue // 父亲 ├── Son1.vue // 儿子1 代码结构 在父亲组件中使用儿子组件,给儿子通过 :date="xxx" 单向传值 <template> <div> <div>爸爸:{{date}

  • JAVA多线程间通讯常用实现方法解析

    如何实现线程间通讯,有如下三种方法: 1.使用Semaphore (信号量)类来控制线程的等待和释放 功能:三个线程 a .b .c 并发运行,b,c 需要 a 线程的数据怎么实现 分析:考虑到多线程的不确定性, 因此我们不能确保 ThreadA 就一定先于 ThreadB 和 ThreadC 前执行,就算 ThreadA先执行了, 我们也无法保证 ThreadA 什么时候才能将变量 num 给初始化完成. 因此我们必须让 ThreadB 和 Thread去等待 ThreadA 完成任何后发出的

随机推荐