在編寫C#windows應用程式的時候我們經常會遇到這種問題,怎麼樣在兩個窗體間傳遞資料呢?以下是我整理的網上的各種方法,在遇到一個實際問題:在form1中打開一個form2視窗作為錄入界面,将錄入的值經轉換後在form1中顯示。 采用了委托的方法,可以實作。(與VC的回調的應用相似)
1.可以通過委托的方法來解決
問題:通過form1做一個錄入界面,将裡邊通過文本框錄入的數值複值給 form2中的listview各列,用3個textbox1.text舉例吧,分别對應listview的3個列。
可以這麼做,如果兩個窗體是在同一個命名空間下
定義一個代理,注意這個代理是全局的:(即同一命名空間下,與Form1,Form2平級的)
public delegate void MyInvoke(string Item1,string Item2,string Item3);
//在窗體From2中有這麼一個回調函數,用于在ListView裡添加一個新項的:
private void UpdateListView(string Item1,string Item2,string Item3)
{
ListView1.Items.Add(Item1);
ListView1.Items[ListView1.Items.Count - 1].SubItems.Add(Item2);
ListView1.Items[ListView1.Items.Count - 1].SubItems.Add(Item3);
}
//比如說點選Form2的一個按鈕彈出Form1進行錄入,在點選按鈕的事件下:
//把委托傳過去
Form1 frmEdit=new Form1(new MyInvoke(UpdateListView));
frmEdit.ShowDialog(this);
//在Form1裡定義一個屬性
private MyInvoke mi=null;
在構造函數中接收這個委托:
public Form1(MyInvoke myInvoke)
{
this.mi=myInvoke;
}
//錄入資料後,點選OK按鈕,在點選事件下:
//回調
this.mi(this.TextBox1.Text,this.TextBox3.Text,this.TextBox3.Text);
this.Close();//關閉Form1
補充:如果我要是想再把form2的值給form1,
Form1 frmEdit=new Form1(new MyInvoke(UpdateListView),string para1,string para2...);
frmEdit.ShowDialog(this);
然後将Form1的構造函數改成可以接收幾個參數的就行了
2.假如主架構為Form1,打開的搜尋對話框是Form2.直接在Form2類中申明一個Form1執行個體:Form1 f1=new Form1();然後就可以通過f1來調用Form1中的域和函數了。其實不是這樣的,你申明的新的Form1執行個體不是原來的那個Form1對象了,這樣操作的是新的Form1中的域和函數,和最先打開的Form1是沒有關系的。
我們要做的是把目前的Form1執行個體傳遞給Form2,如果是這樣的話,問題就很好解決了。
方法1:首先,我們在Form2中定義:
private Form1 mF_Form
我們更改Form2的構造函數為有參數的
public Form2 ( Form1 myForm )
{
// Windows 窗體設計器支援所必需的
InitializeComponent ( ) ;
this.mF_Form = myForm ; /這樣在Form1中申明Form2的時候就把Form1的執行個體傳遞過來了
// TODO: 在 InitializeComponent 調用後添加任何構造函數代碼
}
在Form1中,我在 要用到Form2的地方申明如下:
Form2 f2=new Form2(this);這裡的this指的就是Form1目前的執行個體,也就是把目前Form1的執行個體通過Form2的構造函數傳遞給Form2類(其實在網上看到過比較蠢的方式,就是在構造函數裡面傳遞要傳遞的資訊如:字元串或是數字等,這樣做很有局限性,不能傳遞其他的,所有我們可以直接傳遞執行個體,來完成傳遞更多的資訊。)
這樣在Form2中使用myForm 就可以對原來的Form1視窗進行操作了。但是你要把要操作的Form1中的域和函數定義成public形式的(這樣可能不安全),此時的myForm就是真正的最開始打開的Form1了,你可以用這個執行個體來進行兩個窗體的通訊了。 ()
3.其實C#中提供了窗體間進行通訊的現成的屬性,呵呵,我們能想到的,微軟也想到了,他們創造的語言其實确實可以說是人性化了。
在Form1類中申明Form2時用如下代碼:
Form2 f2=new Form2();//類Form2中的構造函數不改,還是無參的
f2.owner=this;這裡的this指的是類Form1目前的執行個體。
//也可以使用函數的方法,給目前執行個體添加一個附屬視窗 代碼:this.AddOwnedForm(f2);
在Form2類的定義中寫如下代碼:
Form1 f1=this.owner;
這樣f1對應的就是原來的Form1的執行個體了,也就可以用這個進行通訊了。但是還是要把不同類之間通路的域和函數定義成public,哎,安全确實是一個問題!!
4.使用靜态類
這個也是我們經常要用到的一種資料互動方法。
下面是定義的一個類:
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("Asp.net");
listData.Add("WebService");
listData.Add("XML");
}
public static ArrayList ListData
{
get{return 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.buttonDel.Text = "删除";
this.buttonDel.Click += new System.EventHandler(this.buttonDel_Click);
this.textBoxAdd.Location = new System.Drawing.Point(188, 12);
this.textBoxAdd.Name = "textBoxAdd";
this.textBoxAdd.Size = new System.Drawing.Size(76, 21);
this.textBoxAdd.TabIndex = 5;
this.textBoxAdd.Text = "";
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(272, 141);
this.Controls.Add(this.textBoxAdd);
this.Controls.Add(this.buttonDel);
this.Controls.Add(this.buttonAdd);
this.Controls.Add(this.listBoxFrm2);
this.Controls.Add(this.buttonOK);
this.Name = "Form2";
this.Text = "Form2";
this.ResumeLayout(false);
}
private void buttonOK_Click(object sender, System.EventArgs e)
{
this.Close();
}
private void buttonAdd_Click(object sender, System.EventArgs e)
{
if(this.textBoxAdd.Text.Trim().Length>0)
{
AppDatas.ListData.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)
{
AppDatas.ListData.RemoveAt(index);
this.listBoxFrm2.Items.RemoveAt(index);
}
else
MessageBox.Show("請選擇删除項!");
}
}
}
總結,我認為使用靜态類比較多的地方就是把應用程式的配置檔案裝載到一個靜态類裡面,讓所有的窗體和其他執行個體都可以通過靜态屬性以及靜态方法使用這些資料,比如三層結構或多層結構都可以通路它,而不是在多個執行個體間傳來傳去。在這裡我們讨論的是Windows窗體,其實在兩個不同的執行個體間互動資料,都可以采用三篇文章中的方案實作,除非是這個類特有的屬性或着方法。現在都講完了,雖然不是什麼高深的東西,但是希望能對一些初學者有所幫助,同時也歡迎各位朋友進行技術交流,共同提高。
分析上面幾種方法:
1. 采用了委托的方法,可以實作。:很好的實作了資料處理與資料顯示的分離,即FORM2(主)顯示與FORM1資料處理,(不需要将FORM2的顯示放在FORM1中)與VC的回調的應用有延續性。并且確定了FORM1中要修改的屬性的私有性。
2. 方法2、3都是傳遞主視窗的引用,比較簡單易用。可以實作FORM2(主)與FORM1所有資料的傳遞(不過需要将要FORM1傳遞和要修改的資料設為PUBLIC),而這樣會存在安全問題。
委托方法可以很好地實作資料的保護
轉載于:https://www.cnblogs.com/wsxg/archive/2012/04/05/2433491.html