【C#】窗體間互相傳值
網上關於C#之間的窗體之間互相傳值其實很坑的。主要有修改要被傳遞數值的窗體的建構函式,然而這種方法,如果你要做開啟一個窗體,然後這個窗體輸入完東西之後傳遞回去,根本就是不知道怎麼實現。之後還有什麼委託delegate事件event大法,這個雖然能夠實現,但我表示自己看了老半天都沒看懂這個C#神特性。
比如如下的例子,在Form1點選“修改”按鈕,將開啟Form2,Form2中有一個文字框,輸入完東西,無論使用者按回車還是點選確認按鈕,都會將輸入結果反饋到Form1的Label1上,如果使用者點右上角的“關閉”按鈕,則不反饋。
同時,注意到,無論是Form1點選“修改”按鈕,Form2會在Form1的位置出現,Form2確定修改之後,Form1同樣會去到Form2的位置。
這個例子主要的核心是顯示如果在兩個窗體之間傳遞數值。
解決方案包含的東西如下:
其中Form2.cs是在解決方案中新建的Windows窗體,Intent.cs是新建的一個C#類。
Intent.cs就是本解決方案的核心,仿造Android的在Activity傳遞數值的思想,搞一個Key-values的字典dict,這個字典,用於存放窗體與窗體之間傳遞的數值。dict左邊的key用string,右邊的values用Object,這樣就是面對不同的數值傳遞都可以應付。同時將這個字典dict直接設定成public static,呼叫不用這麼麻煩。
using System; using System.Collections.Generic; using System.Text; namespace FormPassValues { class Intent { public static Dictionary<string, Object> dict = new Dictionary<string, Object>(); } }
之後的Form1,禁用最大化、最小化按鈕佈局如下:
Form1.cs的程式碼如下:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace FormPassValues { public partial class Form1 : Form { public Form1() { InitializeComponent(); this.StartPosition = FormStartPosition.CenterScreen;//設定form1的開始位置為螢幕的中央 } private void button1_Click(object sender, EventArgs e) { Form2 form2 = new Form2();//宣告要使用form2窗體 //將form1當前的位置壓入Intent中的dict Intent.dict["form1_top"] = this.Top; Intent.dict["form1_left"] = this.Left; Intent.dict["form1_label1_text"] = label1.Text; if (form2.ShowDialog() == DialogResult.OK) {//這個判斷,將會等到form2被關閉之後才執行,如果form2返回一個OK值 this.Top = (int)Intent.dict["form2_top"];//更新form1的位置 this.Left = (int)Intent.dict["form2_left"]; label1.Text = Intent.dict["form2_textbox1_text"] + "";//更新form1的內容 } } } }
之後Form2,同樣禁用最大化、最小化按鈕之後佈局如下:
具體的Form2.cs的程式碼如下,textbox1按下Enter確定輸入是仿造《【C#】利用System.IO中的File類中的ReadAllText與WriteAllText輸入輸出小檔案》(點選開啟連結)的處理,這裡不再贅述了。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace FormPassValues
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
//在初始化的時候,取出Intent中的需要屬性,更新自己的位置,同時更新textbox1的內容
this.Top = (int)Intent.dict["form1_top"];
this.Left = (int)Intent.dict["form1_left"];
textBox1.Text = Intent.dict["form1_label1_text"] + "";
textBox1.Focus();//設定焦點停留在textBox1中
textBox1.Select();//同時選中textBox1中的所有文字,必須先有焦點,再選中
}
private void button1_Click(object sender, EventArgs e)
{
//關閉form2之間,將要傳給form1的值壓入Intent中的dict
Intent.dict["form2_top"] = this.Top;
Intent.dict["form2_left"] = this.Left;
Intent.dict["form2_textbox1_text"] = textBox1.Text;
this.DialogResult = DialogResult.OK;//同時設定返回值為OK,不設定的話,預設返回Cancel
this.Close();
}
private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Enter)//一旦使用者在輸入過程中輸入Enter
{
this.button1_Click(sender,e);//則執行button1“確定”按鈕點選事件
}
}
}
}
縱觀上述程式,沒用到什麼高深的語法與C#中的一些新的特性,都是所有程式語言都存在的容器類,關於C#容器類的操作請看《【C#】利用正則表示式判斷輸入是否為純數字、容器類》(點選開啟連結),C#的容器還可以直接像python那樣操作,譬如Intent.dict["form2_top"] = this.Top;之句,如果dict中沒有form2_top這一項,就自動將this.Top這個值壓進去,如果存在,就修改為this.Top。你無須理會到底存在不存在這項。
在窗體間互相傳值,關鍵是理解,在form2.ShowDialog();之後,form1的程式碼是在這裡中斷、形成一個斷點的,知道form2被關閉之後,程式碼才繼續向下執行的。原理是與《【C#】檔案選擇對話方塊OpenFileDialog與下列列表ComboBox》(點選開啟連結)一模一樣的,因此自己定一個公有的Intent全域性類就能夠解決這個問題。
同時,這裡再補充一下form2.ShowDialog();之後form2是個模態對話方塊,就是form2不關閉,form1不能進行任何操作。
如果單純地form2.Show(),form2則與form1沒有任何關係了,form2也將沒有任何返回值,form1的程式碼也不會中斷在form2.Show()。