如果知道要添加的控件类型,我们往往很容易将子控件添加到我们需要的地方,在WEBFORM中,我们往往用一个PLACEHOLDER,将它做为一个容器,在这个容器中添加子控件,在WINFORM中,我们可以用容器类控件动态地增加子控件, 例如PANAL,GROUPBOX,等等都是容器型控件,在此就不做掇述,方法如下:
Button btn = new Button();
panal.Controls.Add(btn);
这样做的弊端就是在事前必需知道这个类是Button类,或者是其它类
一般在大型的项目中不用这种做法,往往是做一个用户控件,先构造一个用户控件的基类,再由此基类派生出需要用到的子类,如下图
![]()
而这种做法也有不好的地方,就是重用性不好,在这个项目中用到的用户控件往往在另一个项目中就得重做一套用户控件,而且调试高度,宽度,字体大小,字体样式等方面不太容易,为此我想到可以将这些数据放到数据库中,因此,我设计了两张表,GroupControl和Controls.
GroupControl中是存放用户控件组的,如上面这样的用户控件有几个,Controls中是放页面上所有的控件的
两个表结构如下
![]()
![]()
GroupID是主键,Instruction是用户控件组的说明,这个表也可以针对实际需求进行扩充,
在第二张表中,我定义GroupID就是确认这个控件是在哪个用户控件组中,ValidatingCheckReg是用于在检查控件在失去焦点时要做的CHECK,LINENUM是这个控件在组中处于哪一行,PostionOfLine是这个控件在这一行中片于左中右等位置.Instruction是用户控件得到焦点时在状态栏中的说明,此表也可以根据实际开发需要进行修改和扩充,
下面先附上代码,以进行分析
using
System;
using
System.Drawing;
using
System.Collections;
using
System.ComponentModel;
using
System.Windows.Forms;
using
System.Configuration;
using
System.Collections.Specialized;
using
System.Data.OleDb;
using
System.Data;
using
System.Text.RegularExpressions;
namespace
WindowsApplication3

...
{

/**//// <summary>
/// DynamicControl の概要の説明です。
/// </summary>
public class DynamicControl : System.Windows.Forms.Form

...{
private System.Windows.Forms.StatusBar statusBar1;
private System.Windows.Forms.StatusBarPanel statusBarPanel1;
private System.Windows.Forms.StatusBarPanel statusBarPanel2;
private System.Windows.Forms.Timer timer1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabPage tabPage1;
private System.ComponentModel.IContainer components;
private const int GroupsRowSpan = 10;
private const int RowsInGroupSpan = 5;

private int[] RowsPostion = new int[]...{50,130,230};
DataTable objDtControl = new DataTable();
private System.Windows.Forms.StatusBarPanel statusBarPanel3;
private System.Windows.Forms.DateTimePicker dateTimePicker1;
private System.Windows.Forms.RichTextBox richTextBox1;
DataTable objdtGroups = new DataTable();
public DynamicControl()

...{
//
// Windows フォーム デザイナ サポートに必要です。
//
InitializeComponent();

//
// TODO: InitializeComponent 呼び出しの後に、コンストラクタ コードを追加してください。
//
}


/**//// <summary>
/// 使用されているリソースに後処理を実行します。
/// </summary>
protected override void Dispose( bool disposing )

...{
if( disposing )

...{
if(components != null)

...{
components.Dispose();
}
}
base.Dispose( disposing );
}


Windows フォーム デザイナで生成されたコード#region Windows フォーム デザイナで生成されたコード

/**//// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
private void InitializeComponent()

...{
this.components = new System.ComponentModel.Container();
this.statusBar1 = new System.Windows.Forms.StatusBar();
this.statusBarPanel1 = new System.Windows.Forms.StatusBarPanel();
this.statusBarPanel2 = new System.Windows.Forms.StatusBarPanel();
this.timer1 = new System.Windows.Forms.Timer(this.components);
this.button1 = new System.Windows.Forms.Button();
this.tabControl1 = new System.Windows.Forms.TabControl();
this.tabPage1 = new System.Windows.Forms.TabPage();
this.statusBarPanel3 = new System.Windows.Forms.StatusBarPanel();
this.dateTimePicker1 = new System.Windows.Forms.DateTimePicker();
this.richTextBox1 = new System.Windows.Forms.RichTextBox();
((System.ComponentModel.ISupportInitialize)(this.statusBarPanel1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.statusBarPanel2)).BeginInit();
this.tabControl1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.statusBarPanel3)).BeginInit();
this.SuspendLayout();
//
// statusBar1
//
this.statusBar1.Location = new System.Drawing.Point(0, 336);
this.statusBar1.Name = "statusBar1";

this.statusBar1.Panels.AddRange(new System.Windows.Forms.StatusBarPanel[] ...{
this.statusBarPanel1,
this.statusBarPanel2,
this.statusBarPanel3});
this.statusBar1.ShowPanels = true;
this.statusBar1.Size = new System.Drawing.Size(664, 22);
this.statusBar1.TabIndex = 1;
this.statusBar1.Text = "statusBar1";
//
// statusBarPanel1
//
this.statusBarPanel1.Width = 200;
//
// statusBarPanel2
//
this.statusBarPanel2.Width = 300;
//
// timer1
//
this.timer1.Enabled = true;
this.timer1.Interval = 1000;
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
//
// button1
//
this.button1.Font = new System.Drawing.Font("MS UI Gothic", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(128)));
this.button1.Location = new System.Drawing.Point(504, 24);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(152, 32);
this.button1.TabIndex = 0;
this.button1.Text = "GetControlByName";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// tabControl1
//
this.tabControl1.Controls.Add(this.tabPage1);
this.tabControl1.Location = new System.Drawing.Point(0, 0);
this.tabControl1.Name = "tabControl1";
this.tabControl1.SelectedIndex = 0;
this.tabControl1.Size = new System.Drawing.Size(496, 328);
this.tabControl1.TabIndex = 2;
//
// tabPage1
//
this.tabPage1.Location = new System.Drawing.Point(4, 21);
this.tabPage1.Name = "tabPage1";
this.tabPage1.Size = new System.Drawing.Size(488, 303);
this.tabPage1.TabIndex = 0;
this.tabPage1.Text = "DynamicControl";
//
// statusBarPanel3
//
this.statusBarPanel3.Text = "statusBarPanel3";
//
// dateTimePicker1
//
this.dateTimePicker1.Location = new System.Drawing.Point(504, 152);
this.dateTimePicker1.Name = "dateTimePicker1";
this.dateTimePicker1.Size = new System.Drawing.Size(152, 19);
this.dateTimePicker1.TabIndex = 4;
//
// richTextBox1
//
this.richTextBox1.Location = new System.Drawing.Point(512, 72);
this.richTextBox1.Name = "richTextBox1";
this.richTextBox1.Size = new System.Drawing.Size(100, 30);
this.richTextBox1.TabIndex = 5;
this.richTextBox1.Text = "richTextBox1";
//
// DynamicControl
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 12);
this.ClientSize = new System.Drawing.Size(664, 358);
this.Controls.Add(this.richTextBox1);
this.Controls.Add(this.dateTimePicker1);
this.Controls.Add(this.tabControl1);
this.Controls.Add(this.statusBar1);
this.Controls.Add(this.button1);
this.Name = "DynamicControl";
this.Text = "DynamicControl";
this.Load += new System.EventHandler(this.DynamicControl_Load);
((System.ComponentModel.ISupportInitialize)(this.statusBarPanel1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.statusBarPanel2)).EndInit();
this.tabControl1.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)(this.statusBarPanel3)).EndInit();
this.ResumeLayout(false);

}
#endregion

private void DynamicControl_Load(object sender, System.EventArgs e)

...{
// string setting = ConfigurationSettings.AppSettings["Button"];
// NameValueCollection nc=(NameValueCollection)ConfigurationSettings.GetConfig("DynamicControl/Test");
//
// string assName = typeof(System.Windows.Forms.Form).AssemblyQualifiedName;
// string assInfo = assName.Substring(assName.IndexOf(","));
// int top = 20;
// for (int i = 0; i < nc.Count; i++)
// {
// Type t = System.Type.GetType("System.Windows.Forms." + nc.AllKeys[i].ToString() + assInfo, true);
//
// Control ctrl = (Control)Activator.CreateInstance(t);
// ctrl.Text = nc[nc.AllKeys[i].ToString()];
// ctrl.Name = nc[nc.AllKeys[i].ToString()];
// ctrl.Top = top;
// ctrl.Left = 10;
// ctrl.BackColor = Color.FromKnownColor(System.Drawing.KnownColor.Desktop) ;
// top += ctrl.Height + 10;
// ctrl.GotFocus += new EventHandler(ctrl_GotFocus);
// tabPage1.Controls.Add(ctrl);
// }

string strCon = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=e:dynamicControl.mdb; Persist Security Info=False;";
OleDbConnection oleCon = new OleDbConnection(strCon);
oleCon.Open();
OleDbCommand oleCom = new OleDbCommand("select * from Controls where Groupid = '00001' order by LineNum", oleCon);
OleDbCommand oleComGroup = new OleDbCommand("select * from GroupControl order by GroupID", oleCon);
OleDbDataAdapter oleDataAdapter = new OleDbDataAdapter(oleCom);
OleDbDataAdapter oleDataAdapterGroup = new OleDbDataAdapter(oleComGroup);
oleDataAdapterGroup.Fill(objdtGroups);
oleDataAdapter.Fill(objDtControl);
string assName = typeof(System.Windows.Forms.Form).AssemblyQualifiedName;
string assInfo = assName.Substring(assName.IndexOf(","));
int[] rowsOfTop = new int[objDtControl.Rows.Count];
int nLine = 0;
foreach (DataRow objDr in objDtControl.Rows)

...{
int nLineNum = Convert.ToInt16(objDr[6].ToString());
if (nLine == 0)

...{
rowsOfTop[nLine] = 30;
}
else if(nLineNum != nLine)

...{
rowsOfTop[nLineNum] = rowsOfTop[nLineNum - 1] + Convert.ToInt16(objDr[8].ToString()) + RowsInGroupSpan;
}
nLine = Convert.ToInt16(objDr[6].ToString());
}
foreach (DataRow objDr in objDtControl.Rows)

...{
Type t = System.Type.GetType("System.Windows.Forms." + objDr[2].ToString() + assInfo, true);

Control ctrl = (Control)Activator.CreateInstance(t);
ctrl.Text = objDr[4].ToString();
ctrl.Name = objDr[3].ToString();
int nLineNum = Convert.ToInt16(objDr[6].ToString());
ctrl.Top = rowsOfTop[nLineNum];
ctrl.Width = Convert.ToInt16(objDr[7].ToString());
ctrl.Height = Convert.ToInt16(objDr[8].ToString());
ctrl.Left = RowsPostion[Convert.ToInt16(objDr[9].ToString()) - 1];
ctrl.BackColor = Color.FromKnownColor(System.Drawing.KnownColor.Desktop);

ctrl.Font = new System.Drawing.Font("MS UI Gothic", 12F);

ctrl.GotFocus += new EventHandler(ctrl_GotFocus);
ctrl.Validating += new CancelEventHandler(ctrl_Validating);
tabPage1.Controls.Add(ctrl);
}

oleCon.Close();
}

private void timer1_Tick(object sender, System.EventArgs e)

...{
statusBarPanel1.Text = DateTime.Now.ToLongDateString();
}
private void ctrl_GotFocus(object sender, System.EventArgs e)

...{
// Control con = (Control) sender as Control;
// statusBarPanel2.Text = con.Name;
Control con = (Control) sender as Control;
foreach (DataRow objDr in objDtControl.Rows)

...{
if (objDr[3].ToString().Equals(con.Name))

...{
statusBarPanel3.Text = objDr[10].ToString();
statusBarPanel2.Text = con.Height.ToString();
}
}
}

private void ctrl_Click(object sender, System.EventArgs e)

...{
Control con = (Control) sender as Control;
statusBarPanel2.Text = con.Name;
}

private void button1_Click(object sender, System.EventArgs e)

...{
foreach(Control ctrl in tabPage1.Controls)

...{
if( ctrl.Name == "txtTest3" )

...{
ctrl.Focus();
}
}
}

private void ctrl_Validating(object sender, System.ComponentModel.CancelEventArgs e)

...{
Control con = (Control) sender as Control;
foreach (DataRow objDr in objDtControl.Rows)

...{
if (objDr[3].ToString().Equals(con.Name))

...{
if (!Regex.IsMatch(con.Text, objDr[5].ToString()))

...{
con.Focus();
e.Cancel = true;
}
}
}
}
}
}
实现的技术就是反射,方法如下
string
assName
=
typeof
(System.Windows.Forms.Form).AssemblyQualifiedName;

string
assInfo
=
assName.Substring(assName.IndexOf(
"
,
"
));

Type t
=
System.Type.GetType(
"
System.Windows.Forms.
"
+
"
Button
"
+
assInfo,
true
);

Control ctrl
=
(Control)Activator.CreateInstance(t);
另一种反射的用法如下
System.Reflection.Assembly asm;
object
obj;
asm
=
System.Reflection.Assembly.Load(
"
example.dll
"
);
obj
=
asm.CreateInstance(
"
person
"
);
con
=
obj
as
Control;
example.dll是这个类所在的程序集,要说明的一点是这个DLL必须在USING中已经引进,
PERSON是要建的一个类名
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1468790