利用反射动态添加控件

          就要元旦了,老板休假,有三天时间自由活动,闲着无事,就想找点事干干,刚好前一个项目中用到了动态添加控件技术,下面就跟大家分享一下我的一些经验

         如果知道要添加的控件类型,我们往往很容易将子控件添加到我们需要的地方,在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()
        
...

        
/// <summary>
        
/// 使用されているリソースに後処理を実行します。
        
/// </summary>

        protected override void Dispose( bool disposing )
        
{
            
if( disposing )
            
{
                
if(components != null)
                
{
                    components.Dispose();
                }

            }

            
base.Dispose( disposing );
        }


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

        
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是要建的一个类名

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值