程序員在.Net平臺下進行WinForm應用程序開發過程當中,常常會遇到窗體之間的相互傳值或者其餘的調用操做,這是在.Net平臺上編寫WinForm程序很重要的一個基礎,網絡上問及這方面的帖子特別多,我作了簡單舉例並將具體的方法作了一個總結。
設計以下的兩個窗體:
From1中button1的功能代碼相對簡單:
Form2 Frm2 = new Form2();
Frm2.Show();
Form2.textbox1.text=textbox1.text;
在輸入最後的代碼時有問題,系統會提示「窗體調用.Form2」並不包含「textbox1」的定義」,看From2中的定義文件中,有「private System.Windows.Forms.TextBox textBox1;」說明Form2窗體中的textbox1是私有的,對外不能訪問,怎麼辦?改動訪問屬性,將「Private」改成「internal」(即在本程序集裏能夠訪問)再運行,系統正常了。
總結:能夠經過改變窗體控件的訪問屬性來進行操做。
系統將窗體控件的訪問屬性默認爲私有,這樣作是遵循了面向對象的封裝原則,因此,咱們仍是將「internal」改回「Private」,那上面的問題怎麼解決?
既然是打開窗體就傳值,那麼在From2中聲明一個構造函數就而後在From2窗體初始化的時候就傳值就能夠了,在From2中聲明新的構造函數:
public Form2(string SValue)
{
this.textBox1.Text = SValue;
}
在From1窗體的button1按鈕的點擊事件中寫以下代碼:
Form2 Frm2 = new Form2(textBox1.Text);
Frm2.Show();
代碼沒有問題,運行時系統報告構造函數錯誤,原來From2(string SValue)的textbox1對象爲空,那麼就是說該代碼運行於初始化事件以前【在窗體或者控件繪製圖形或者其餘操做時也會遭遇這樣的問題,即在對象初始化以前進行相似操做固然會出現問題】,因此改動代碼以下:
public Form2(string SValue)
{
InitializeComponent();//加入初始化事件
this.textBox1.Text = SValue;
}
運行,系統正常了。
總結:能夠定義一個傳遞對象而且在窗體的構造函數中接收傳遞對象來處理窗體的傳值操做。
如今處理Form1中的button2事件,它的做用是在Form2窗體打開的狀況下改變該窗體中的textbox1的值。
寫代碼時必須找到打開的窗體而後再賦值,由於對Frm2定義只在button1_Click方法體中存在,因此沒法在本方法體中利用Frm2,那麼是否是在把Frm2的做用域延伸到整個Form1窗體(在Form1中定義)就能夠利用Frm2了。可是這個沒有解決問題,關鍵在於Form2中的textbox1是私有的,因此,咱們沒有必要在Form1中定義對Form2的引用。
找到目前打開的Form2窗體的實例對象,能夠應用Application對象,它包含了一個集合對象OpenForms,經過檢索它能夠找到目前打開的窗體。
textbox1 既然是私有的,那麼咱們能夠經過定義屬性來操做它,以下:
public string Textbox1
{
get { return textBox1.Text; }
set { textBox1.Text = value; }
}
那麼Form1中的button2的點擊事件代碼能夠這樣寫了:
((Form2)Application.OpenForms["Form2"]).Textbox1 =textBox1.Text;
運行系統,正常。
問題又來了,當你打開多個Form2實例對象窗體時,上面的代碼只改變最早打開的那個,其餘的沒有反應。
由於Application.OpenForms["Form2"])是按Form2名稱檢索【索引器】,檢索到後就返回了,因此只有最早打開的Form2對象接收了操做,改動Form1中的button2的點擊事件代碼以下:
foreach (Form Frm in Application.OpenForms)
{
if (Frm.Text == "Form2")
{
((Form2)Frm).Textbox1 = textBox1.Text;
}
}
這樣就能夠對全部打開的Form2對象實例進行相同的操做了。
總結:根據封裝原則,經過屬性來封裝對象內的字段操做提升安全性,檢索Application.OpenForms能夠對系統目前打開的窗體進行操做。
窗體傳值是一個事件的改變觸發另一個方法或者動做,對於此類應用咱們通常經過委託來實現。
在Form2中寫下以下代碼:
public delegate void MyDelegateChange(string Str);//定義委託
public MyDelegateChange MyChange;//聲明
//定義動做
private void MyChangeFunction(string Str)
{
textBox1.Text = Str;
}
在Form2的button2的點擊事件中寫下以下代碼:
MyChange = new MyDelegateChange(MyChangeFunction);
在Form1的button2的點擊事件中寫下以下代碼:
Form2 Frm2 = new Form2();
foreach (Form Frm in Application.OpenForms)
{
if (Frm.Text == "Form2")
{
Frm2 = (Form2)Frm;
}
}
Frm2.MyChange(textBox1.Text);
運行系統,正常傳值。
咱們還能夠經過委託定義事件來處理。
在Form2中寫下入下代碼:
public delegate void MyDelegateChange(string Str);//定義委託
public event MyDelegateChange OnMyChange;//聲明事件
public void Form2_OnMyChange(string Str)
{
//事件動做
textBox1.Text = Str;
}
在Form1的button2的點擊事件中寫下以下代碼:
Form2 Frm2 = new Form2();
Frm2.Form2_OnMyChange(textBox1.Text);
運行,系統正常傳值。
總結:能夠經過委託和事件來進行窗體之間的傳值操做。
其實,上面是秉承面向對象的原則來處理,看起來麻煩,以下方法能夠隨意地達到目的:
Form Frm2 = new Form2();
foreach (Form Frm in Application.OpenForms)
{
if (Frm.Text == "Form2")
{
Frm2 = Frm;
}
}
Frm2.Controls["textbox1"].Text = textBox1.Text;
在寫代碼過程當中,經過上面的方式咱們只能操做控件共有的屬性和方法,若是是控件特有的,能夠經過引用的方式進行處理,假設Form2上面有個CheckBox1的控件,如今在Form1的Button2的點擊事件中操做它,能夠按以下的方式:
CheckBox CB1=new CheckBox();
CB1 = Frm2.Controls["checkBox1"] as CheckBox;
CB1.Checked = true;
好比,如今Form2窗體上有個名爲button1的按鈕,你但願觸發它的點擊事件,能夠這樣寫:
((Button)Frm2.Controls["button1"]).PerformClick();
總結:咱們能夠經過檢索集合對象來進行窗體之間相互靈活的操做。
網絡上,對於對話框窗口的傳值的問題也不少,解決辦法是若是你想獲取一個窗口的返回值,直接調用就能夠。 固然也能夠經過以下方法來調用,好比在Form1中打開了Form2,點擊Form2上面的按鈕更改Form1上面的textBox1的值,能夠以下寫: this.Owner.Controls[「textbox1」].text=」123」; 另外還有一些其餘方法,好比: 1、咱們還能夠經過API的調用來進行窗體之間的相互操做,只是如今已沒有必要這樣去作了; 2、設置一個公用類來傳參數,通常不可取; 3、設置一個接口來傳參數,缺乏靈活性也不可取;