本文主要讲述如何根据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. ASP.NET常用的SqlDbHelper类

    请引用 using System.Data;using System.Data.SqlClient; 两个命名空间. 可以满足常用的数据集,读取多条数据,以及增删改操作 代码: /// <sum ...

  2. CGContextTranslateCTM: invalid context 0x0. If you want to see the backtrace, please set CG_CONTEXT_SHOW_BACKTRACE environmental variable.

    最近在测试的过程中, 发现了SpringBoar的一个问题: SpringBoard[53] <Error>: CGContextTranslateCTM: invalid context ...

  3. 咱们来聊聊JS中的异步,以及如何异步,菜鸟版

    为什么需要异步?why?来看一段代码. 问题1: for(var i=0;i<100000;i++){ } alert('hello world!!!'); 这段代码的意思是执行100...次后 ...

  4. Oracle 11g系列:数据库

    1.创建Oracle数据库 创建Oracle数据库的最常用工具为Database Configuration Assistant(数据库配置助手),依次选择[开始]|[所有程序]|[Oracle-Or ...

  5. Struts2第一个例子Hello World!

    1.首先用eclipse新建一个动态web项目Struts2Demo1: (把Default output floder由build\classes改成WebContent\WEB-INF\class ...

  6. Java多线程系列--“JUC原子类”02之 AtomicLong原子类

    概要 AtomicInteger, AtomicLong和AtomicBoolean这3个基本类型的原子类的原理和用法相似.本章以AtomicLong对基本类型的原子类进行介绍.内容包括:Atomic ...

  7. Yii的学习(4)--Active Record

    摘自Yii官网:http://www.yiiframework.com/doc/guide/1.1/zh_cn/database.ar 在官网原文的基础上添加了CDbCriteria的详细用法. 虽然 ...

  8. windows环境下跑hadoop自带的wordcount遇到的问题

    hadoop环境自己之前也接触过,搭建的是一个伪分布的环境,主从节点都在我自己的机子上,即127.0.0.1,当初记得步骤很多很麻烦的样子(可能自己用ubuntu还不够熟练),包括myeclipse. ...

  9. Web 前端开发精华文章集锦(jQuery、HTML5、CSS3)【系列二十】

    <Web 前端开发精华文章推荐>2013年第八期(总第二十期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各种增强网站用户体验的 jQuery 插件,展示前沿的 HTML5 和 C ...

  10. Eclipse10个最有用的快捷键[From: Internet]

    1. ctrl+shift+r:打开资源这可能是所有快捷键组合中最省时间的了.这组快捷键可以让你打开你的工作区中任何一个文件,而你只需要按下文件名或mask名中的前几个字母,比如applic*.xml ...