1. 程式人生 > >【C#】窗體間互相傳值

【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()。