已阅读5页,还剩26页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
在.net中轻松掌控windows窗体间的数据交互(一) zhzuo(秋枫) windows 窗体是用于 microsoft windows 应用程式研发的、基于 .net framework 的新平台。此框架提供一个有条理的、面向对象的、可扩展的类集,他使你得以研发丰富的 windows 应用程式。一个windows窗体就代表了.net架构里的system.windows.forms.form类的一个实例。 作者在csdn技术论坛.net板块下的c#分类经常看到有人问起怎么在两个form间传递数据,访问修改对方窗体里面的值。对于有经验的程式员来说不是什么高深的东西,而对于初学者来说这些基础的东西往往是个问题,并且存在这种现象,往往比较复杂的东西他们会,要用什么了就去学什么,实际上并没有真正的去理解掌控他,基础不扎实,所以就有了想通过自己对窗体编程积累的经验来写一些这方面的文章,以供学.net的朋友参考,也借此机会同各位朋友进行交流,写得不合理的地方请各位朋友提宝贵意见,下面我分了三个部分来讲。 一使用带参数的构造函数 我们要做的准备工作就是新建两个窗体,下面是两个窗体的布局,非常简单: 说明:form1为主窗体,包含控件:文本框textboxfrm1,多选框checkboxfrm1和按钮buttonedit; form2为子窗体,包含控件:文本框textboxfrm2,多选框checkboxfrm2和按钮buttonok,buttoncancel。 当我们新建一个窗体的时候,设计器会生成默认的构造函数: public form2() initializecomponent(); 他不带参数,既然我们要把form1中的一些数据传到form2中去,为什么不在form2的构造函数里做文章呢? 假设我们要实现使form2中的文本框显示form1里textboxfrm1的值,修改子窗体的构造函数: public form2(string text) initializecomponent(); this.textboxfrm2.text = text; 增加form1中的修改按钮点击事件,处理函数如下: private void buttonedit_click(object sender, system.eventargs e) form2 formchild = new form2(this.textboxfrm1.text); formchild.show(); 我们把this.textboxfrm1.text作为参数传到子窗体构造函数,以非模式方式打开,这样打开的formchild的文本框就显示了”主窗体”文本,是不是非常简单,接下来我们传一个boolean数据给子窗体。 public form2(string text,bool checkedvalue) initializecomponent(); this.textboxfrm2.text = text; this.checkboxfrm2.checked = checkedvalue; 在主窗体中的修改按钮点击处理,我采用了打开模式窗口的方式,其实在这个例子中看不出有什么分别, private void buttonedit_click(object sender, system.eventargs e) form2 formchild = new form2(this.textboxfrm1.text,this.checkboxfrm1.checked); formchild.showdialog(); 结果在预料之中,不过这里明显存在不足,在子窗体里的数据修改后不能传给主窗体,也就是说主窗体不受子窗体的影响。而在实际的研发过程中我们经常使用子窗体来修改主窗体里面的数据,那怎么解决呢? 在.net中有两种类型,值类型和引用类型。值类型是从valuetype继承而来,而valuetype又是从object继承;对于引用类型他直接继承object类型。这下让我们看看怎样通过form2来修改form1里的数据。 还是让我们来修改form2的代码。 private textbox textboxfrm12; private checkbox checkboxfrm12; public form2(textbox heckbo,checkbox heckbox) initializecomponent(); this.textboxfrm2.text = heckbo.text; this.checkboxfrm2.checked = heckbox.checked; this.textboxfrm12 = heckbo; this.checkboxfrm12 = heckbox; 目前我们传了两个引用类型的数据:textbox类型,和checkbox;另外在form2中增加了两个类数据成员textboxfrm12、checkboxfrm12用来分别保存构造函数传来的变量,不过他们并不属于form2的controls容器。修改form2的确定按钮点击事件函数: private void buttonok_click(object sender, system.eventargs e) this.textboxfrm12.text = this.textboxfrm2.text; this.checkboxfrm12.checked = this.checkboxfrm2.checked; this.close(); 上面的代码我们通过把textboxfrm2的text和checkboxfrm2.checked赋给textboxfrm12和checkboxfrm12完成了对主窗体中的textboxfrm1和checkboxfrm2的修改,因为textboxfrm1和textboxfrm12是同一个引用,而checkboxfrm2和checkboxfrm12也是。 到这里为止功能是实现了,不过总觉得不是非常合理,让两个窗体控件传来传去,目前我举一个恰当一点的例子。 修改了两个窗体: 说明:在这个例子中我们的两个窗体都加了一个listbox用来显示arraylist中的内容。 主窗体中控件:listboxfrm1,buttonedit; 子窗体中控件:listboxfrm2,textboxadd,buttonadd,buttonedit,buttonok。 这次我们用arraylist来作为传递数据,在form1中定义类数据成员: private arraylist listdata1; 在构造函数中增加了对listdata1进行内存分配,并生成数据最终绑定到listboxfrm1, public form1() initializecomponent(); this.listdata1 = new arraylist(); this.listdata1.add(dotnet); this.listdata1.add(c#); this.listdata1.add(); this.listdata1.add(webservice); this.listdata1.add(xml); this.listboxfrm1.datasource = this.listdata1; 另外,对修改按钮点击事件处理函数的修改如下: private void buttonedit_click(object sender, system.eventargs e) form2 formchild = new form2(this.listdata1); formchild.showdialog(); this.listboxfrm1.datasource = null; this.listboxfrm1.datasource = this.listdata1; 相对和主窗体,对子窗体作相应修改,也在form2中增加了类数据成员: private arraylist listdata2; 用来保存对主窗体中listdata1的引用。 修改构造函数: public form2(arraylist listdata) initializecomponent(); this.listdata2 = listdata; foreach(object o in this.listdata2) this.listboxfrm2.items.add(o); 这里让listdata2同listdata1指向同一个引用;另外没有对listboxfrm进行绑定,采用了填充。 好了,下面是对数据操作的时候了。 添加处理函数代码如下: private void buttonadd_click(object sender, system.eventargs e) if(this.textboxadd.text.trim().length0) this.listdata2.add(this.textboxadd.text.trim(); this.listboxfrm2.items.add(this.textboxadd.text.trim(); else messagebox.show(请输入添加的内容!); 删除处理代码如下: private void buttondel_click(object sender, system.eventargs e) int index = this.listboxfrm2.selectedindex; if(index!=-1) this.listdata2.removeat(index); this.listboxfrm2.items.removeat(index); else messagebox.show(请选择删除项或没有可删除的项!); 退出form2子窗体: private void buttonok_click(object sender, system.eventargs e) this.close(); 编译运行程式,在子窗体中对数据进行修改,关闭后,主窗体就会显示更新后的数据。 这里有一点要提醒一下,比较两个例子,我们都传的是引用类型,一个是string,另一个是arraylist,为什么string类型不能修改主窗体的数据呢?其实在.net中对string类型的修改并不是修改原来的值,原来的值没有变化,而是重新生成一个新的字符串,下面是个非常好的说明。 public class zzconsole stathread static void main(string args) string str1 = abc; string str2 = str1; str1 = 123; console.writeline(str1); console.writeline(-); console.writeline(str2); console.writeline(-); arraylist al1 = new arraylist(); al1.add(abc); arraylist al2 = al1; al2.add(123); foreach(object o in al1) console.writeline(string)o); console.writeline(-); foreach(object o in al2) console.writeline(string)o); console.readline(); 运行一下看看输出结果就明白了,另外对值类型的数据操作要使用ref关键字。 总结,我们通过带参数的构造函数实现了窗体间的数据交互,代码看上去也比较清晰,在实际研发过程中,能把dataset,datatable,或是dataview当作参数,当然如果只是想修改一行,能传个datarow或datarowview。在下面的文章中我们来看看怎样使用另外两种方法来实现数据的交互。 在.net中轻松掌握windows窗体间的数据交互(二) zhzuo(秋枫) 在.net中轻松掌握windows窗体间的数据交互(一)一文中我们讲了使用带参数的构造函数来实现窗体间的数据传递,我认为是用的比较多的一种,接下来让我们看看另外两种实现方法。 二给窗体添加属性或方法 1使用form类的owner属性 获取或设置拥有此窗体的窗体。若要使某窗体归另一个窗体所有,请为其 owner 属性分配一个对将成为所有者的窗体的引用。当一个窗体归另一窗体所有时,它便随着所有者窗体最小化和关闭。例如,如果 form2 归窗体 form1 所有,则关闭或最小化 form1 时,也会关闭或最小化 form2。并且附属窗体从不显示在其所有者窗体后面。可以将附属窗体用于查找和替换窗口之类的窗口,当选定所有者窗体时,这些窗口不应消失。若要确定某父窗体拥有的窗体,请使用ownedforms属性。 上面是sdk帮助文档上讲的,下面我们就来使用它。 首先还是使用第一篇文章中的第二个例子,窗体如下: 说明:在这个例子中我们的两个窗体都加了一个listbox用来显示arraylist中的内容。 主窗体中控件:listboxfrm1,buttonedit; 子窗体中控件:listboxfrm2,textboxadd,buttonadd,buttonedit,buttonok。 主窗体中还是定义类数据成员, private arraylist listdata1; 在构造函数里实例化它,填充数据,最后绑定到listboxfrm1。 构造函数如下: public form1() initializecomponent(); this.listdata1 = new arraylist(); this.listdata1.add(dotnet); this.listdata1.add(c#); this.listdata1.add(); this.listdata1.add(webservice); this.listdata1.add(xml); this.listboxfrm1.datasource = this.listdata1; 主窗体的修改按钮处理函数: private void buttonedit_click(object sender, system.eventargs e) form2 formchild = new form2(); formchild.owner = this; formchild.showdialog(); this.listboxfrm1.datasource = null; this.listboxfrm1.datasource = this.listdata1; 我们设置了formchild.owner为this,这样,子窗体和主窗体就有联系了, 当然我们也可以改成如下: private void buttonedit_click(object sender, system.eventargs e) form2 formchild = new form2(); formchild.showdialog(this); this.listboxfrm1.datasource = null; this.listboxfrm1.datasource = this.listdata1; 不过这样还不行,目前主窗体的listdata1变量外部访问不到, private arraylist listdata1; 必须修改为public访问修饰符, public arraylist listdata1; 也可以通过属性(property)来实现, public arraylist listdata1 getreturn this.listdata1; 这里我采用属性,感觉语法更灵活,清楚。 下面是对form2的修改, 构造函数又恢复原貌了。 public form2() initializecomponent(); 另外又新增了一个窗体的load事件,在它的事件处理函数中来获取主窗体中的数据, private void form2_load(object sender, system.eventargs e) form1 pareform = (form1)this.owner; this.listdata2 = pareform.listdata1; foreach(object o in this.listdata2) this.listboxfrm2.items.add(o); 有人会问,为什么不把上面的代码放到构造函数里面去呢?如下不是更好, public form2() initializecomponent(); form1 pareform = (form1)this.owner; this.listdata2 = pareform.listdata1; foreach(object o in this.listdata2) this.listboxfrm2.items.add(o); 那我会对你说错了,因为在主窗体修改按钮被点击后,开始执行 form2 formchild = new form2(); 而在form2的实例化过程中会在构造函数中执行 form1 pareform = (form1)this.owner; 而这时的this.owner是没有值的,为空引用,那么下面的代码肯定也出问题, this.listdata2 = pareform.listdata1; foreach(object o in this.listdata2) this.listboxfrm2.items.add(o); 当整个form2实例化完成后,才会执行 formchild.owner = this; 这条代码,所以使用了form2_load事件。 那怎样可以不使用form2_load事件呢?等下面我们来修改代码实现它。 下面的子窗体代码没有变化, private void buttonadd_click(object sender, system.eventargs e) if(this.textboxadd.text.trim().length0) this.listdata2.add(this.textboxadd.text.trim(); this.listboxfrm2.items.add(this.textboxadd.text.trim(); else messagebox.show(请输入添加的内容!); private void buttondel_click(object sender, system.eventargs e) int index = this.listboxfrm2.selectedindex; if(index!=-1) this.listdata2.removeat(index); this.listboxfrm2.items.removeat(index); else messagebox.show(请选择删除项!); private void buttonok_click(object sender, system.eventargs e) this.close(); 好了,结果同第一篇中的一样,子窗体能修改主窗体的值。 2使用自定义属性或方法 下面我们来讲讲怎样使用自定义属性或方法来完成数据修改功能而不使用form2_load事件。 主窗体的修改按钮点击处理函数如下: private void buttonedit_click(object sender, system.eventargs e) form2 formchild = new form2(); formchild.listdata2 = this.listdata1; formchild.showdialog(); this.listboxfrm1.datasource = null; this.listboxfrm1.datasource = this.listdata1; 并且我们去掉了主窗体的listdata1属性, /public arraylist listdata1 / / getreturn this.listdata1; / 而在子窗体中加上listdata2属性, public arraylist listdata2 set this.listdata2 = value; foreach(object o in this.listdata2) this.listboxfrm2.items.add(o); 也可以把属性改成方法, public void setlistdata(arraylist listdata) this.listdata2 = listdata; foreach(object o in this.listdata2) this.listboxfrm2.items.add(o); 而在主窗体的修改按钮处理函数中也要相应改动: formchild.listdata2 = this.listdata1; 改为 formchild.setlistdata(this.listdata1); 总结,我们通过form类的owner属性来建立主从窗体间的桥梁,这个是不是类似于把主窗体作为子窗体的构造函数参数传入实现的功能差不多;另外又采用了属性和方法来完成数据的交互,我觉得这种实现方法很实用,特别是用在不需要实例化类或着已经有了实例的情况下传递数据。下一篇文章我们来讲如何使用静态类来完成数据的交互。在.net中轻松掌握Windows窗体间的数据交互(三) zhzuo(秋枫) 在第一篇和第二篇文章中我们使用带参数的构造函数、属性以及方法实现了数据的交互,接下来要讲的是使用静态类来完成窗体间的数据交互。这个也是我们经常要用到的一种数据交互方法。 三使用静态类 下面是定义的一个类: using System; using System.Collections; namespace ZZ public class AppDatas private static ArrayList listData; static AppDatas() listData = new ArrayList(); listData.Add(DotNet); listData.Add(C#); listData.Add(A); listData.Add(WebService); listData.Add(XML); public static ArrayList ListData getreturn listData; public static ArrayList GetListData() return listData; 上面包含了一个静态类成员,listData,一个静态构造函数static AppDatas(),用来初始化listData的数据。还有一个静态属性ListData和一个静态GetListData()方法,他们实现了同样的功能就是返回listData。 由于前面两篇文章已经讲了很多,这里不细说了,下面是完整的代码: Form1.cs文件 using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; namespace ZZ public class Form1 : System.Windows.Forms.Form private System.Windows.Forms.Button buttonEdit; private System.Windows.Forms.ListBox listBoxFrm1; private System.ComponentModel.Container components = null; public Form1() InitializeComponent(); this.listBoxFrm1.DataSource = AppDatas.ListData; protected override void Dispose( bool disposing ) if( disposing ) if(components != null) components.Dispose(); base.Dispose( disposing ); STAThread static void Main() Application.Run(new Form1(); private void InitializeComponent() this.buttonEdit = new System.Windows.Forms.Button(); this.listBoxFrm1 = new System.Windows.Forms.ListBox(); this.SuspendLayout(); this.buttonEdit.Location = new System.Drawing.Point(128, 108); this.buttonEdit.Name = buttonEdit; this.buttonEdit.TabIndex = 1; this.buttonEdit.Text = 修改; this.buttonEdit.Click += new System.EventHandler(this.buttonEdit_Click); this.listBoxFrm1.ItemHeight = 12; this.listBoxFrm1.Location = new System.Drawing.Point(12, 8); this.listBoxFrm1.Name = listBoxFrm1; this.listBoxFrm1.Size = new System.Drawing.Size(108, 124); this.listBoxFrm1.TabIndex = 2; this.AutoScaleBaseSize = new System.Drawing.Size(6, 14); this.ClientSize = new System.Drawing.Size(208, 141); this.Controls.Add(this.listBoxFrm1); this.Controls.Add(this.buttonEdit); this.Name = Form1; this.Text = Form1; this.ResumeLayout(false); private void buttonEdit_Click(object sender, System.EventArgs e) Form2 formChild = new Form2(); formChild.ShowDialog(); this.listBoxFrm1.DataSource = null; this.listBoxFrm1.DataSource = AppDatas.ListData; Form2.cs文件 using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; namespace ZZ public class Form2 : System.Windows.Forms.Form private System.Windows.Forms.Button buttonOK; private System.ComponentModel.Container components = null; private System.Windows.Forms.ListBox listBoxFrm2; private System.Windows.Forms.Button buttonAdd; private System.Windows.Forms.Button buttonDel; private System.Windows.Forms.TextBox textBoxAdd; public Form2() InitializeComponent(); foreach(object o in AppDatas.ListData) this.listBoxFrm2.Items.Add(o); protected override void Dispose( bool disposing ) if( disposing ) if(components != null) components.Dispose(); base.Dispose( disposing ); private void InitializeComponent() this.buttonOK = new System.Windows.Forms.Button(); this.listBoxFrm2 = new System.Windows.Forms.ListBox(); this.buttonAdd = new System.Windows.Forms.Button(); this.buttonDel = new System.Windows.Forms.Button(); this.textBoxAdd = new System.Windows.Forms.TextBox(); this.SuspendLayout(); this.buttonOK.Location = new System.Drawing.Point(188, 108); this.buttonOK.Name = buttonOK; this.buttonOK.TabIndex = 0; this.buttonOK.Text = 确定; this.buttonOK.Click += new System.EventHandler(this.buttonOK_Click); this.listBoxFrm2.ItemHeight = 12; this.listBoxFrm2.Location = new System.Drawing.Point(8, 8); this.listBoxFrm2.Name = listBoxFrm2; this.listBoxFrm2.Size = new System.Drawing.Size(168, 124); this.listBoxFrm2.TabIndex = 2; this.buttonAdd.Location = new System.Drawing.Point(188, 44); this.buttonAdd.Name = buttonAdd; this.buttonAdd.TabIndex = 3; this.buttonAdd.Text = 增加; this.buttonAdd.Click += new System.EventHandler(this.buttonAdd_Click); this.buttonDel.Location = new System.Drawing.Point(188, 76); this.buttonDel.Name = buttonDel; this.buttonDel.TabIndex = 4; this.butt
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 纤维打包带生产线项目投资计划书
- 废盐资源循环利用项目投标书
- 2025-2030智慧城市基础设施建设项目评估及发展前景研究
- 2025-2030智慧图书馆系统市场供需与教育行业发展指南
- 2025-2030智慧图书馆领域应用现状投资规划发展分析
- 2025-2030智慧医院行业市场竞争格局需求分析投资评估规划报告
- 2025-2030智慧制衣行业市场调研分析发展前景投资策略研究报告
- 无取向硅钢生产线项目投资计划书
- 2025-2030智慧农业行业种植模式市场发展创新分析研究
- 2025-2030智慧农业行业市场现状供需分析研究投资前景规划分析研究报告
- 医学检验课件完整版
- 汽车发动机构造与维修中职PPT完整全套教学课件
- 泰国历史概况课件
- 新社会阶层人士的统战工作-3
- 声律启蒙详解全文-声律启蒙下全文
- 施工现场安全文明专项检查表(深基坑施工)
- 新生儿肺出血-课件
- qcr - 铁路桥梁工程风险管理技术规范
- 《现当代文学》课程教学大纲
- 人工智能第2章知识表示课件
- 机动车检测站应急预案
评论
0/150
提交评论