本文主要讲述如何根据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