本文主要讲述如何根据UI配置来动态生成控件, 并添加到窗体上来构建UI窗体,当用户在每个控件上完成输入操作后,程序通过遍历控件并用拼接字符串的方式动态生成Insert SQL语句,进而实现了将UI上的值,保存到数据库。

1 UI配置

  首先第一步,需要在数据库中定义UI配置,这里为了简便,用DataTable模拟了数据,如果是复杂的情况,可以再多一些属性的定义,如下所示:

             //实际从数据库加载
DataTable dtUIConfig = new DataTable();
dtUIConfig.Columns.Add("name");
dtUIConfig.Columns.Add("title");
dtUIConfig.Columns.Add("size");
dtUIConfig.Columns.Add("location");
dtUIConfig.Columns.Add("type");
dtUIConfig.Columns.Add("config"); dtUIConfig.Rows.Add(new object[] { "ID", "ID:", "160,30", "0,0", "textbox", "" });
dtUIConfig.Rows.Add(new object[] { "name", "用户名:", "160,30", "0,0", "textbox", "" });
dtUIConfig.Rows.Add(new object[] { "password", "密码:", "160,30", "0,0", "passwordtext", "" });
dtUIConfig.Rows.Add(new object[] { "sex", "性别:", "160,30", "0,0", "combobox", "Man,Female" });
dtUIConfig.Rows.Add(new object[] { "emp", "职员:", "160,30", "0,0", "CustomComboBox", "datagridview" });
dtUIConfig.Rows.Add(new object[] { "dept", "部门:", "160,30", "0,0", "CustomComboBox", "treeview" });
dtUIConfig.Rows.Add(new object[] { "details", "明细:", "440,200", "0,0", "datagridview", "select * from test" });
dtUIConfig.Rows.Add(new object[] { "btnSave", "保存", "160,30", "0,0", "button", "" });

2 获取最长的标签

  由于一般的控件,例如文本框等,前面都有一个标签,由于不同的标题长度不一,为了界面整齐,可以动态计算所有标题的长度,并获取最大的长度,作为所有标签的长度。同理获取所有控件的最大配置长度,当然了类似表格等控件需要独立换行,不在此处理范围,如下所示:

             int leftMargin = ;
int topMargin = ;
int totolwidth = this.Width - - leftMargin; Point currentLocation = new Point(leftMargin, topMargin);
Point nextLocation = new Point(leftMargin, topMargin);
int label_control_width = ;
int y = nextLocation.Y; int labelMaxLength = ;
int controlMaxLength = ; int lastY = ;
//UI engine
foreach (DataRow dr in dtUIConfig.Rows)
{ //计量字符串长度
SizeF maxSize = this.CreateGraphics().MeasureString(dr["title"].ToString(), this.Font);
if (labelMaxLength < maxSize.Width)
{
labelMaxLength = int.Parse(maxSize.Width.ToString(""));
}
if (controlMaxLength < int.Parse(dr["size"].ToString().Split(',')[]))
{
controlMaxLength = int.Parse(dr["size"].ToString().Split(',')[]);
}
}

3 UI Builder

  在获得最长的标签后,可以根据UI配置的控件类型,用程序来动态生成控件,并添加到窗体上,如果有自定义的控件,也可以添加,如下所示:

             //ui builder
foreach (DataRow dr in dtUIConfig.Rows)
{
if (dr["type"].ToString().ToLower() == "button")
{
Label label = new Label();
label.Location = new Point(nextLocation.X, nextLocation.Y);
label.Width = labelMaxLength;//max size
label.Text ="";
//-----------------------------------
Button ctrlItem = new Button();
ctrlItem.Location = new Point(label.Right + label_control_width, nextLocation.Y);
ctrlItem.Width = int.Parse(dr["size"].ToString().Split(',')[]);
ctrlItem.Height = int.Parse(dr["size"].ToString().Split(',')[]);
ctrlItem.Name = dr["name"].ToString();
ctrlItem.Text = dr["title"].ToString();
// ctrlItem.Font = this.Font;
ctrlItem.Click += new EventHandler(ctrlItem_Click);
//-------------------------------------------------------------
nextLocation.X = ctrlItem.Right + ;
lastY = ctrlItem.Bottom + ;
if (nextLocation.X >= totolwidth)
{
nextLocation.Y = ctrlItem.Bottom + ;
nextLocation.X = currentLocation.X;
}
this.Controls.Add(label);
this.Controls.Add(ctrlItem); } //-------------------------------------------------
if (dr["type"].ToString().ToLower() == "CustomComboBox".ToLower())
{
Label label = new Label();
label.Location = new Point(nextLocation.X, nextLocation.Y);
label.Width = labelMaxLength;//max size
label.Text = dr["title"].ToString();
//----------------------------------- //datagridview
if((dr["config"].ToString().ToLower()=="datagridview"))
{
CustomComboBox ctrlItem = new CustomComboBox();
ctrlItem.Location = new Point(label.Right + label_control_width, nextLocation.Y);
ctrlItem.Width = int.Parse(dr["size"].ToString().Split(',')[]);
ctrlItem.Height = int.Parse(dr["size"].ToString().Split(',')[]);
ctrlItem.Name = dr["name"].ToString();
DataGridView gridView = new DataGridView();
gridView.Columns.Add("ID", "ID");
gridView.Columns.Add("Name", "Name");
gridView.Columns.Add("Level", "Level");
ctrlItem.DropDownControl = gridView;
gridView.Rows.Add(new object[] { "", "jack", "" });
gridView.Rows.Add(new object[] { "", "wang", "" });
gridView.Font = this.Font;
ctrlItem.DropDownControlType = enumDropDownControlType.DataGridView;
ctrlItem.DisplayMember = "Name";
ctrlItem.ValueMember = "ID";
//-------------------------------------------------------------
nextLocation.X = ctrlItem.Right + ;
lastY = ctrlItem.Bottom + ;
if (nextLocation.X >= totolwidth)
{
nextLocation.Y = ctrlItem.Bottom + ;
nextLocation.X = currentLocation.X;
}
this.Controls.Add(label);
this.Controls.Add(ctrlItem);
}
else if (dr["config"].ToString().ToLower() == "treeview")
{
CustomComboBox ctrlItem = new CustomComboBox();
ctrlItem.Location = new Point(label.Right + label_control_width, nextLocation.Y);
ctrlItem.Width = int.Parse(dr["size"].ToString().Split(',')[]);
ctrlItem.Height = int.Parse(dr["size"].ToString().Split(',')[]);
ctrlItem.Name = dr["name"].ToString();
//静态变量 2个时候默认就是最后一个
treeView1.Font = this.Font;
ctrlItem.DropDownControlType = enumDropDownControlType.TreeView;
ctrlItem.DropDownControl = this.treeView1;
//not empty
ctrlItem.DisplayMember = "Name";
ctrlItem.ValueMember = "ID";
//-------------------------------------------------------------
nextLocation.X = ctrlItem.Right + ;
lastY = ctrlItem.Bottom + ;
if (nextLocation.X >= totolwidth)
{
nextLocation.Y = ctrlItem.Bottom + ;
nextLocation.X = currentLocation.X;
}
this.Controls.Add(label);
this.Controls.Add(ctrlItem); }
else
{
} }
//---------------------------------------------------------------
//强制换行
if (dr["type"].ToString().ToLower() == "datagridview")
{
//Label label = new Label();
//label.Location = new Point(nextLocation.X, nextLocation.Y);
//label.Width = labelMaxLength;//max size
//label.Text = dr["title"].ToString();
//-----------------------------------
DataGridView ctrlItem = new DataGridView();
//强制换行
ctrlItem.Location = new Point(currentLocation.X, lastY);
ctrlItem.Width = int.Parse(dr["size"].ToString().Split(',')[]);
ctrlItem.Height = int.Parse(dr["size"].ToString().Split(',')[]);
ctrlItem.Name = dr["name"].ToString(); string connString = "server=.\\sql2008r2; database=GC管理; Trusted_Connection=True; ";
MkMisII.DAO.SqlHelper.DefaultConnectionString = connString;
DataTable dtC = MkMisII.DAO.SqlHelper.GetDataTableBySQL(dr["config"].ToString());
if (dtC != null)
{
ctrlItem.DataSource = dtC;
}
//-------------------------------------------------------------
//nextLocation.X = ctrlItem.Right + 8;
//lastY = ctrlItem.Bottom + 16;
//if (nextLocation.X >= totolwidth)
//{
nextLocation.Y = ctrlItem.Bottom + ;
nextLocation.X = currentLocation.X;
//} this.Controls.Add(ctrlItem); }
//-------------------------------------------------
if (dr["type"].ToString().ToLower() == "textbox")
{
Label label = new Label();
label.Location = new Point(nextLocation.X, nextLocation.Y);
label.Width = labelMaxLength;//max size
label.Text = dr["title"].ToString();
//-----------------------------------
TextBox ctrlItem = new TextBox();
ctrlItem.Location = new Point(label.Right + label_control_width, nextLocation.Y);
ctrlItem.Width = int.Parse(dr["size"].ToString().Split(',')[]);
ctrlItem.Height = int.Parse(dr["size"].ToString().Split(',')[]);
ctrlItem.Name = dr["name"].ToString(); //-------------------------------------------------------------
nextLocation.X = ctrlItem.Right + ;
lastY = ctrlItem.Bottom + ;
if (nextLocation.X >= totolwidth)
{
nextLocation.Y = ctrlItem.Bottom + ;
nextLocation.X = currentLocation.X;
}
this.Controls.Add(label);
this.Controls.Add(ctrlItem); }
//----------------------------------------------------------
if (dr["type"].ToString().ToLower() == "combobox")
{
Label label = new Label();
label.Location = new Point(nextLocation.X, nextLocation.Y);
label.Width = labelMaxLength;
label.Text = dr["title"].ToString(); //-----------------------------------
ComboBox ctrlItem = new ComboBox();
ctrlItem.Location = new Point(label.Right + label_control_width, nextLocation.Y);
ctrlItem.Width = int.Parse(dr["size"].ToString().Split(',')[]);
ctrlItem.Height = int.Parse(dr["size"].ToString().Split(',')[]);
ctrlItem.Name = dr["name"].ToString();
string[] items = dr["config"].ToString().Split(',');
foreach (string item in items)
{
ctrlItem.Items.Add(item);
}
//-------------------------------------------------------------
nextLocation.X = ctrlItem.Right + ;
lastY = ctrlItem.Bottom + ;
if (nextLocation.X >= totolwidth)
{
nextLocation.Y = ctrlItem.Bottom + ;
nextLocation.X = currentLocation.X;
} this.Controls.Add(label);
this.Controls.Add(ctrlItem); } if (dr["type"].ToString().ToLower() == "passwordtext")
{
Label label = new Label();
label.Location = new Point(nextLocation.X, nextLocation.Y);
label.Width = labelMaxLength;
label.Text = dr["title"].ToString(); //-----------------------------------
TextBox ctrlItem = new TextBox();
ctrlItem.PasswordChar = '*';
ctrlItem.Location = new Point(label.Right + label_control_width, nextLocation.Y);
ctrlItem.Width = int.Parse(dr["size"].ToString().Split(',')[]);
ctrlItem.Height = int.Parse(dr["size"].ToString().Split(',')[]);
ctrlItem.Name = dr["name"].ToString(); //-------------------------------------------------------------
nextLocation.X = ctrlItem.Right + ;
lastY = ctrlItem.Bottom + ;
if (nextLocation.X >= totolwidth)
{
nextLocation.Y = ctrlItem.Bottom + ;
nextLocation.X = currentLocation.X;
}
this.Controls.Add(label);
this.Controls.Add(ctrlItem); }
}

4 生成保存SQL

  单击保存按钮,我们通过遍历窗体控件,来动态获取值,然后进行SQL 拼接,有了SQL就可以对数据进行CURD操作了,如下所示:

         string SQL = "";
//save
void ctrlItem_Click(object sender, EventArgs e)
{
try
{
string preSQL="Insert into Users(";
string postSQL = " ) values ( ";
foreach (DataRow dr in dtUIConfig.Rows)
{
if (dr["type"].ToString() != "button" && dr["type"].ToString() != "datagridview")
{
Control[] ctrl = this.Controls.Find(dr["name"].ToString(), true);
if (ctrl != null)
{
if (ctrl.Length == )
{
if (!dic.Keys.Contains(dr["name"].ToString()))
{
preSQL += string.Format("'{0}',", dr["name"].ToString());
postSQL += string.Format("'{0}',", ctrl[].Text);
//dic.Add(dr["name"].ToString(), ctrl[0].Text);
}
} }
} }
SQL = preSQL.TrimEnd(',') + postSQL.TrimEnd(',') + ")";
MessageBox.Show(SQL,"insert SQL");
//Save data to database ...
}
catch (Exception ex)
{ } }

5 效果

  运行程序,界面如下所示:

  大小调整后,会自动进行UI重新布局,如下图所示:

  单击保存,生成SQL

C#如何根据配置实现动态窗体的更多相关文章

  1. Struts2-整理笔记(二)常量配置、动态方法调用、Action类详解

    1.修改struts2常量配置(3种) 第一种 在str/struts.xml中添加constant标签 <struts> <!-- 如果使用使用动态方法调用和include冲突 - ...

  2. JavaWeb_(Struts2框架)struts.xml核心配置、动态方法调用、结果集的处理

    此系列博文基于同一个项目已上传至github 传送门 JavaWeb_(Struts2框架)Struts创建Action的三种方式 传送门 JavaWeb_(Struts2框架)struts.xml核 ...

  3. 微软Azure配置中心 App Configuration (三):配置的动态更新

    写在前面 我在前文: <微软Azure配置中心 App Configuration (一):轻松集成到Asp.Net Core>已经介绍了Asp.net Core怎么轻易的接入azure ...

  4. 前端引擎初步设计稿 -通过配置生成动态页面 ,LandaSugar平台 .NET-C#-MVC

    公司准备开发出一款项目开发平台 LandaSugar,分为 前端引擎.工作引擎.数据引擎 三大块,开发人员只需要对三大模块进行相应的配置便能够完成一个定制项目的开发. 听起来貌似是异想天开,但是是否真 ...

  5. Nutch的配置以及动态网站的抓取

    http://blog.csdn.net/jimanyu/article/details/5619949 一:配置Nutch: 1.解压缩的nutch后,以抓取http://www.163.com/为 ...

  6. HttpModule在Web.config的配置和动态配置

    学习笔记 ASP.Net处理Http Request时,使用Pipeline(管道)方式,由各个HttpModule对请求进行处理,然后到达 HttpHandler,HttpHandler处理完之后, ...

  7. Springboot多数据源配置--数据源动态切换

    在上一篇我们介绍了多数据源,但是我们会发现在实际中我们很少直接获取数据源对象进行操作,我们常用的是jdbcTemplate或者是jpa进行操作数据库.那么这一节我们将要介绍怎么进行多数据源动态切换.添 ...

  8. 【原创】一篇学会vue路由配置 、 动态路由 、多层路由(实例)

    先来看看效果图: 为了方便讲解,我没有使用vue脚手架,如果需要的,可以留言跟我要.不多说开工: 首先,html先组上 <div id="app"> <div&g ...

  9. MyBatis的核心配置、动态sql、关联映射(快速总结)

    MyBatis的核心对象和配置 #1. SqlSessionFactory对象: 单个数据库映射关系经过编译的内存镜像: 作用:创建SQLSession对象. //读取配置文件 InputSteam ...

随机推荐

  1. PC端和移动端地址适配

    判断当前页面的打开方式是pc还是移动设备,如果是移动设备,跳转到对应移到端网站的方法: 方法一.还是用@media screen 思路:css使用媒体查询,当屏幕小于760px时,使某个元素的样式发生 ...

  2. AJAX大文件切割上传以及带进度条。

    分块传输的原理就是利用HTML5新增的文件slice截取函数. 代码如下: html: <input id="f" type="file" name=&q ...

  3. OOCSS入门学习

    对于面向对象大家肯定都有多多少少的了解,这里所说的OOCSS就是说面向对象的CSS,得说明的是OOCSS并不是一门新语言也不是什么库,而是一种概念和javascript面向对象一样. 可能你这样写过C ...

  4. SQL Server的Execute As与连接池结合使用的测试

    简介     在SQL Server中,Execute As关键字允许当前账户在特定上下文中以另一个用户或登录名的身份执行SQL语句,比如用户张三有权限访问订单表,用户李四并没有权限访问订单表,那么给 ...

  5. CSS层叠

    前面的话 层叠样式表CSS最基本的一个特性就是层叠.冲突的声明通过层叠进行排序,由此确定最终的文档表示.而这个过程的核心就是选择器及其相关声明的特殊性.重要性.来源及继承机制.本文将详细介绍CSS层叠 ...

  6. java中异常注意的细节1

    /* public class Test{ public static void main(String[] args){ int i=0; try{ func();//区别就是该函数抛出的异常被封装 ...

  7. [OpenCV] Samples 08: edge

    Canny edge detector 效率高,效果可控. TrackBar的使用. 技巧:gray找边缘后作为mask去CopyTo(). #include "opencv2/core/u ...

  8. JS实现单击按钮后弹出新的窗口页面

    点击按钮后,弹出指定大小的页面窗口. 效果图: 源码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN&qu ...

  9. Android requires compiler compliance level 5.0 or 6.0. Found '1.8' instead. Please use Android Tools>Fix project Properties.

    重装操作系统之后,或者破坏了Android的开发环境之后,需要重新配置好Android的开发环境.但是配置好后,导入原有的项目时,报错: Android requires compiler compl ...

  10. 20套高品质的 Mobile & Web 界面 PSD 素材免费下载

    在这里,我们向大家呈现20个新鲜出炉的矢量的免费 PSD 素材.这些素材来自著名的设计社区——Dribbble,这个网站的用户不断发布各种精美的用户界面,图标和网站布局,以帮助激励他人.这些免费素材不 ...