本文主要講述如何根據UI配置來動態生成控件, 並添加到窗體上來構建UI窗體,當用戶在每個控件上完成輸入操作後,程序通過遍歷控件並用拼接字符串的方式動態生成Insert SQL語句,進而實現了將UI上的值,保存到數據庫。
首先第一步,需要在數據庫中定義UI配置,這裡為了簡便,用DataTable模擬了數據,如果是復雜的情況,可以再多一些屬性的定義,如下所示:
1 //實際從數據庫加載 2 DataTable dtUIConfig = new DataTable(); 3 dtUIConfig.Columns.Add("name"); 4 dtUIConfig.Columns.Add("title"); 5 dtUIConfig.Columns.Add("size"); 6 dtUIConfig.Columns.Add("location"); 7 dtUIConfig.Columns.Add("type"); 8 dtUIConfig.Columns.Add("config"); 9 10 dtUIConfig.Rows.Add(new object[] { "ID", "ID:", "160,30", "0,0", "textbox", "" }); 11 dtUIConfig.Rows.Add(new object[] { "name", "用戶名:", "160,30", "0,0", "textbox", "" }); 12 dtUIConfig.Rows.Add(new object[] { "password", "密碼:", "160,30", "0,0", "passwordtext", "" }); 13 dtUIConfig.Rows.Add(new object[] { "sex", "性別:", "160,30", "0,0", "combobox", "Man,Female" }); 14 dtUIConfig.Rows.Add(new object[] { "emp", "職員:", "160,30", "0,0", "CustomComboBox", "datagridview" }); 15 dtUIConfig.Rows.Add(new object[] { "dept", "部門:", "160,30", "0,0", "CustomComboBox", "treeview" }); 16 dtUIConfig.Rows.Add(new object[] { "details", "明細:", "440,200", "0,0", "datagridview", "select * from test" }); 17 dtUIConfig.Rows.Add(new object[] { "btnSave", "保存", "160,30", "0,0", "button", "" });
由於一般的控件,例如文本框等,前面都有一個標簽,由於不同的標題長度不一,為了界面整齊,可以動態計算所有標題的長度,並獲取最大的長度,作為所有標簽的長度。同理獲取所有控件的最大配置長度,當然了類似表格等控件需要獨立換行,不在此處理范圍,如下所示:
1 int leftMargin = 20; 2 int topMargin = 20; 3 int totolwidth = this.Width - 220 - leftMargin; 4 5 Point currentLocation = new Point(leftMargin, topMargin); 6 Point nextLocation = new Point(leftMargin, topMargin); 7 int label_control_width = 2; 8 int y = nextLocation.Y; 9 10 int labelMaxLength = 20; 11 int controlMaxLength = 160; 12 13 int lastY = 0; 14 //UI engine 15 foreach (DataRow dr in dtUIConfig.Rows) 16 { 17 18 //計量字符串長度 19 SizeF maxSize = this.CreateGraphics().MeasureString(dr["title"].ToString(), this.Font); 20 if (labelMaxLength < maxSize.Width) 21 { 22 labelMaxLength = int.Parse(maxSize.Width.ToString("0")); 23 } 24 if (controlMaxLength < int.Parse(dr["size"].ToString().Split(',')[0])) 25 { 26 controlMaxLength = int.Parse(dr["size"].ToString().Split(',')[0]); 27 } 28 }
在獲得最長的標簽後,可以根據UI配置的控件類型,用程序來動態生成控件,並添加到窗體上,如果有自定義的控件,也可以添加,如下所示:
1 //ui builder 2 foreach (DataRow dr in dtUIConfig.Rows) 3 { 4 if (dr["type"].ToString().ToLower() == "button") 5 { 6 Label label = new Label(); 7 label.Location = new Point(nextLocation.X, nextLocation.Y); 8 label.Width = labelMaxLength;//max size 9 label.Text =""; 10 //----------------------------------- 11 Button ctrlItem = new Button(); 12 ctrlItem.Location = new Point(label.Right + label_control_width, nextLocation.Y); 13 ctrlItem.Width = int.Parse(dr["size"].ToString().Split(',')[0]); 14 ctrlItem.Height = int.Parse(dr["size"].ToString().Split(',')[1]); 15 ctrlItem.Name = dr["name"].ToString(); 16 ctrlItem.Text = dr["title"].ToString(); 17 // ctrlItem.Font = this.Font; 18 ctrlItem.Click += new EventHandler(ctrlItem_Click); 19 //------------------------------------------------------------- 20 nextLocation.X = ctrlItem.Right + 8; 21 lastY = ctrlItem.Bottom + 16; 22 if (nextLocation.X >= totolwidth) 23 { 24 nextLocation.Y = ctrlItem.Bottom + 16; 25 nextLocation.X = currentLocation.X; 26 } 27 this.Controls.Add(label); 28 this.Controls.Add(ctrlItem); 29 30 } 31 32 33 //------------------------------------------------- 34 if (dr["type"].ToString().ToLower() == "CustomComboBox".ToLower()) 35 { 36 Label label = new Label(); 37 label.Location = new Point(nextLocation.X, nextLocation.Y); 38 label.Width = labelMaxLength;//max size 39 label.Text = dr["title"].ToString(); 40 //----------------------------------- 41 42 43 //datagridview 44 if((dr["config"].ToString().ToLower()=="datagridview")) 45 { 46 CustomComboBox ctrlItem = new CustomComboBox(); 47 ctrlItem.Location = new Point(label.Right + label_control_width, nextLocation.Y); 48 ctrlItem.Width = int.Parse(dr["size"].ToString().Split(',')[0]); 49 ctrlItem.Height = int.Parse(dr["size"].ToString().Split(',')[1]); 50 ctrlItem.Name = dr["name"].ToString(); 51 DataGridView gridView = new DataGridView(); 52 gridView.Columns.Add("ID", "ID"); 53 gridView.Columns.Add("Name", "Name"); 54 gridView.Columns.Add("Level", "Level"); 55 ctrlItem.DropDownControl = gridView; 56 gridView.Rows.Add(new object[] { "001", "jack", "9" }); 57 gridView.Rows.Add(new object[] { "002", "wang", "9" }); 58 gridView.Font = this.Font; 59 ctrlItem.DropDownControlType = enumDropDownControlType.DataGridView; 60 ctrlItem.DisplayMember = "Name"; 61 ctrlItem.ValueMember = "ID"; 62 //------------------------------------------------------------- 63 nextLocation.X = ctrlItem.Right + 8; 64 lastY = ctrlItem.Bottom + 16; 65 if (nextLocation.X >= totolwidth) 66 { 67 nextLocation.Y = ctrlItem.Bottom + 16; 68 nextLocation.X = currentLocation.X; 69 } 70 this.Controls.Add(label); 71 this.Controls.Add(ctrlItem); 72 } 73 else if (dr["config"].ToString().ToLower() == "treeview") 74 { 75 CustomComboBox ctrlItem = new CustomComboBox(); 76 ctrlItem.Location = new Point(label.Right + label_control_width, nextLocation.Y); 77 ctrlItem.Width = int.Parse(dr["size"].ToString().Split(',')[0]); 78 ctrlItem.Height = int.Parse(dr["size"].ToString().Split(',')[1]); 79 ctrlItem.Name = dr["name"].ToString(); 80 //靜態變量 2個時候默認就是最後一個 81 treeView1.Font = this.Font; 82 ctrlItem.DropDownControlType = enumDropDownControlType.TreeView; 83 ctrlItem.DropDownControl = this.treeView1; 84 //not empty 85 ctrlItem.DisplayMember = "Name"; 86 ctrlItem.ValueMember = "ID"; 87 //------------------------------------------------------------- 88 nextLocation.X = ctrlItem.Right + 8; 89 lastY = ctrlItem.Bottom + 16; 90 if (nextLocation.X >= totolwidth) 91 { 92 nextLocation.Y = ctrlItem.Bottom + 16; 93 nextLocation.X = currentLocation.X; 94 } 95 this.Controls.Add(label); 96 this.Controls.Add(ctrlItem); 97 98 99 } 100 else 101 { 102 } 103 104 105 } 106 //--------------------------------------------------------------- 107 //強制換行 108 if (dr["type"].ToString().ToLower() == "datagridview") 109 { 110 //Label label = new Label(); 111 //label.Location = new Point(nextLocation.X, nextLocation.Y); 112 //label.Width = labelMaxLength;//max size 113 //label.Text = dr["title"].ToString(); 114 //----------------------------------- 115 DataGridView ctrlItem = new DataGridView(); 116 //強制換行 117 ctrlItem.Location = new Point(currentLocation.X, lastY); 118 ctrlItem.Width = int.Parse(dr["size"].ToString().Split(',')[0]); 119 ctrlItem.Height = int.Parse(dr["size"].ToString().Split(',')[1]); 120 ctrlItem.Name = dr["name"].ToString(); 121 122 string connString = "server=.\\sql2008r2; database=GC管理; Trusted_Connection=True; "; 123 MkMisII.DAO.SqlHelper.DefaultConnectionString = connString; 124 DataTable dtC = MkMisII.DAO.SqlHelper.GetDataTableBySQL(dr["config"].ToString()); 125 if (dtC != null) 126 { 127 ctrlItem.DataSource = dtC; 128 } 129 //------------------------------------------------------------- 130 //nextLocation.X = ctrlItem.Right + 8; 131 //lastY = ctrlItem.Bottom + 16; 132 //if (nextLocation.X >= totolwidth) 133 //{ 134 nextLocation.Y = ctrlItem.Bottom + 16; 135 nextLocation.X = currentLocation.X; 136 //} 137 138 this.Controls.Add(ctrlItem); 139 140 } 141 //------------------------------------------------- 142 if (dr["type"].ToString().ToLower() == "textbox") 143 { 144 Label label = new Label(); 145 label.Location = new Point(nextLocation.X, nextLocation.Y); 146 label.Width = labelMaxLength;//max size 147 label.Text = dr["title"].ToString(); 148 //----------------------------------- 149 TextBox ctrlItem = new TextBox(); 150 ctrlItem.Location = new Point(label.Right + label_control_width, nextLocation.Y); 151 ctrlItem.Width = int.Parse(dr["size"].ToString().Split(',')[0]); 152 ctrlItem.Height = int.Parse(dr["size"].ToString().Split(',')[1]); 153 ctrlItem.Name = dr["name"].ToString(); 154 155 //------------------------------------------------------------- 156 nextLocation.X = ctrlItem.Right + 8; 157 lastY = ctrlItem.Bottom + 16; 158 if (nextLocation.X >= totolwidth) 159 { 160 nextLocation.Y = ctrlItem.Bottom + 16; 161 nextLocation.X = currentLocation.X; 162 } 163 this.Controls.Add(label); 164 this.Controls.Add(ctrlItem); 165 166 } 167 //---------------------------------------------------------- 168 if (dr["type"].ToString().ToLower() == "combobox") 169 { 170 Label label = new Label(); 171 label.Location = new Point(nextLocation.X, nextLocation.Y); 172 label.Width = labelMaxLength; 173 label.Text = dr["title"].ToString(); 174 175 //----------------------------------- 176 ComboBox ctrlItem = new ComboBox(); 177 ctrlItem.Location = new Point(label.Right + label_control_width, nextLocation.Y); 178 ctrlItem.Width = int.Parse(dr["size"].ToString().Split(',')[0]); 179 ctrlItem.Height = int.Parse(dr["size"].ToString().Split(',')[1]); 180 ctrlItem.Name = dr["name"].ToString(); 181 string[] items = dr["config"].ToString().Split(','); 182 foreach (string item in items) 183 { 184 ctrlItem.Items.Add(item); 185 } 186 //------------------------------------------------------------- 187 nextLocation.X = ctrlItem.Right + 8; 188 lastY = ctrlItem.Bottom + 16; 189 if (nextLocation.X >= totolwidth) 190 { 191 nextLocation.Y = ctrlItem.Bottom + 16; 192 nextLocation.X = currentLocation.X; 193 } 194 195 this.Controls.Add(label); 196 this.Controls.Add(ctrlItem); 197 198 } 199 200 if (dr["type"].ToString().ToLower() == "passwordtext") 201 { 202 Label label = new Label(); 203 label.Location = new Point(nextLocation.X, nextLocation.Y); 204 label.Width = labelMaxLength; 205 label.Text = dr["title"].ToString(); 206 207 //----------------------------------- 208 TextBox ctrlItem = new TextBox(); 209 ctrlItem.PasswordChar = '*'; 210 ctrlItem.Location = new Point(label.Right + label_control_width, nextLocation.Y); 211 ctrlItem.Width = int.Parse(dr["size"].ToString().Split(',')[0]); 212 ctrlItem.Height = int.Parse(dr["size"].ToString().Split(',')[1]); 213 ctrlItem.Name = dr["name"].ToString(); 214 215 //------------------------------------------------------------- 216 nextLocation.X = ctrlItem.Right + 8; 217 lastY = ctrlItem.Bottom + 16; 218 if (nextLocation.X >= totolwidth) 219 { 220 nextLocation.Y = ctrlItem.Bottom + 16; 221 nextLocation.X = currentLocation.X; 222 } 223 this.Controls.Add(label); 224 this.Controls.Add(ctrlItem); 225 226 } 227 }
單擊保存按鈕,我們通過遍歷窗體控件,來動態獲取值,然後進行SQL 拼接,有了SQL就可以對數據進行CURD操作了,如下所示:
1 string SQL = ""; 2 //save 3 void ctrlItem_Click(object sender, EventArgs e) 4 { 5 try 6 { 7 string preSQL="Insert into Users("; 8 string postSQL = " ) values ( "; 9 foreach (DataRow dr in dtUIConfig.Rows) 10 { 11 if (dr["type"].ToString() != "button" && dr["type"].ToString() != "datagridview") 12 { 13 Control[] ctrl = this.Controls.Find(dr["name"].ToString(), true); 14 if (ctrl != null) 15 { 16 if (ctrl.Length == 1) 17 { 18 if (!dic.Keys.Contains(dr["name"].ToString())) 19 { 20 preSQL += string.Format("'{0}',", dr["name"].ToString()); 21 postSQL += string.Format("'{0}',", ctrl[0].Text); 22 //dic.Add(dr["name"].ToString(), ctrl[0].Text); 23 } 24 } 25 26 } 27 } 28 29 } 30 SQL = preSQL.TrimEnd(',') + postSQL.TrimEnd(',') + ")"; 31 MessageBox.Show(SQL,"insert SQL"); 32 //Save data to database ... 33 } 34 catch (Exception ex) 35 { 36 37 } 38 39 }
運行程序,界面如下所示:
大小調整後,會自動進行UI重新布局,如下圖所示:
單擊保存,生成SQL