winform動態生成窗體並實現傳值返回

某店長發表於2019-03-26

目前還在苦逼的折騰練手作,碰到了關於生成窗體和傳值的需求
首先是生成窗體的需求:
首先,首頁有眾多按鈕,都是用來指向各個功能視窗的,一個個是編寫程式碼的話,太麻煩了;
其次,設計一個通用的篩選視窗,給不同的資料表介面進行查詢篩選,在編寫查詢條件時,要給一些專案比較多的欄位提供一個瀏覽查詢功能,同樣需要動態生成窗體……
這個需求倒是挺容易就找到了解決方案,直接貼出程式碼以供參考


		string strForm = (sender as Button).Tag.ToString();//我在設計介面裡,已經將每個按鈕的tag填好了需要建立的視窗類名
        object[] obj = new object[1] { sqlcon };//我傳了個mysql連線字串,顯然,在呼叫的視窗類裡,需要寫一個相應的建構函式,這個就不必展示了吧
        Form form = GetInstance(strForm, obj) as Form;//呼叫下面的那個方法
        form.show();			
        //以上是我寫在二十多個按鈕共同的click事件方法裡的建立視窗程式碼
        
        ///這個方法,或者說這裡面的這句程式碼,是關鍵所在             
		public static object GetInstance(string instanceName, params object[] param)
        {
            return Assembly.Load(Assembly.GetAssembly(typeof(Index)).GetName().Name).CreateInstance(typeof(Index).Namespace + "." + instanceName, true, BindingFlags.CreateInstance, null, param, System.Threading.Thread.CurrentThread.CurrentCulture, null);
            //index,是我的主視窗類名。至於這句程式碼的功能,看VS的提示,雖然很長,但還是挺好懂的
        }

這段程式碼我改了改,就拿到了篩選視窗使用。
但接著新的問題就來了,怎麼拿到使用者選擇的返回值?

以下分隔線內是個我沒解決的問題,可以當作是廢話跳過
=====================
我曾經用過中間視窗方案,也就是新增個視窗(myForm),基本什麼都沒有,就是寫入一個私有的string欄位(result),再配上一個公開的獲取方法(Result)。
然後讓所有基本資料視窗繼承這個中間視窗,這樣,當使用者選擇完成後,就用 視窗.Result 拿到返回值。
不幸的是,不知是winform有毒,還是VS有毒(其實我更想說BUG),這個方法經常會這樣:
在這裡插入圖片描述
wuliao就是我做的其中一個基礎資料視窗,繼承中間視窗Form1後,設計器就會出錯誤,折騰多次,依舊沒能搞明白其中的問題所在——曾經用簡單的重啟,就不再提示了,但同樣的方法用第二次就無效了(微軟,你的BUG是聖鬥士級別的麼),依舊報錯
====================
嗯,廢話結束,在確實需要傳回值的情況下,考慮過使用委託,也就是將父視窗方法傳給子視窗,不幸的是,在使用上述的動態新建視窗方法時,VS報錯:方法組不能作為object 傳遞!
抱著試試也不會掉塊肉的想法,我直接把當前視窗(this)作為引數,塞了進去,測試成功——在子視窗將當前視窗標題改寫成功。
於是,就有了下面這個程式碼:

			父視窗的方法名略(引數略)
			{
				前略
				string strForm = “視窗名”;
                chuandi cd = new chuandi();//建立一個僅用來傳遞返回值的物件
                object[] obj = new object[2] { sqlcon ,cd };
                Form form = GetInstance(strForm, obj) as Form;
                if (form.ShowDialog() == DialogResult.OK)
                	dataGridView1.CurrentCell.Value = cd.zhi;
			}
			
			///僅用來傳遞返回值的物件類
			public class chuandi
		    {
		        public string zhi { get; set; }
		    }

			///某個基礎資料視窗
			public partial class wuliao : Form
		    {
		    	private chuandi rcd;//宣告物件,準備用來接收
		    	///建構函式
		        public wuliao(string sqlcon,chuandi cd)
		        {
		            InitializeComponent();
		            rcd = cd;
		        }
		        ///查詢結束,確定返回值的方法
		        private void resultGet(string r)
		        {
		        	rcd.zhi = r;//返回值
		        	this.DialogResult = DialogResult.OK;
		        	this.close();
		        }
		    } 

目前看來,這個方案還沒發現什麼問題,如有大佬覺得不行,歡迎批評指點

相關文章