博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

DataGrid动态创建模板列[收集]

Posted on 2007-08-15 13:02  大胸宝腚  阅读(712)  评论(3)    收藏  举报
DataGrid是ASP.NET开发中最常用的控件之一,我们知道,DataGrid中的列包括绑定列,按钮列,超级连接列,模板列等类型,模板列当然是最复杂也最灵活的一种了。在一些项目中,我们需要在DataGrid中显示的列在开发阶段并不能确定,而将其留到了运行时。比如,我们要在DataGrid中显示一张工资表,而各个公司的工资项目并不相同,为适合各不同公司的需要,我们要让用户可以自定义工资项目,这时我们就需要动态创建列。下面的代码演示如何动态生成各种列。
一、绑定列(BoundColumn)

二、按钮列(ButtonColumn)

三、超级连接列(HyperLinkColumn)

四、模板列(TemplateColumn)


/// <summary>
    
/// 类 名 称:DataGridTextBoxTemplate
    
/// 内容摘要:文本框模板类
    
/// </summary>
    public class DataGridTextBoxTemplate : ITemplate             
    { 
        
// 数据列名
        private string fieldName;
        
// 控件ID
        private string ctrlID;
         
        
/**//// <summary>
        
/// 构造方法
        
/// </summary>
        
/// <param name="strCtrlID">控件ID</param>
        
/// <param name="strFieldName">数据列名</param>
        public DataGridTextBoxTemplate(string strCtrlID, string strFieldName)                          
        {
            fieldName 
= strFieldName;
            ctrlID 
= strCtrlID;
        }
           
        
/**//// <summary>
        
/// 实现ITemplate的InstantiateIn方法
        
/// </summary>
        
/// <param name="container">控件容器</param>
        public void InstantiateIn(System.Web.UI.Control container)        
        {
            TextBox tb 
= new TextBox();
            tb.ID 
= ctrlID;
            tb.Width 
= Unit.Percentage(100);
            
//tb.Text = "";
            tb.DataBinding += new EventHandler(TextBoxTemplate_DataBinding);
            container.Controls.Add(tb);
        }
            
        
/**//// <summary>
        
/// 绑定事件处理
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>
        private void TextBoxTemplate_DataBinding(object sender, System.EventArgs e)        
        {
            TextBox tb;
            tb 
= (TextBox)sender;
            DataGridItem container 
= (DataGridItem) tb.NamingContainer;
            tb.Text 
+= DataBinder.Eval(container.DataItem, fieldName);
            
//tb.Text += "</TD></TR>";
        }
    }
这个DataGridTextBoxTemplate类只能适用于创建内部存放TextBox的模板列,如果按照这样的方式,我们需要创建一个CheckBox列就需要创建一个DataGridCheckBoxTemplate,需要创建一个DropDownList列就需要创建一个DataGridDropDownListTemplate类,这样的话,有多少控件就需要多少个模板类,显然,这样的类不具备通用性。
/// <summary>
    
/// 类 名 称:DataGridTemplate
    
/// 内容摘要:通用模板类
    
/// </summary>
    public class DataGridTemplate : ITemplate
    {
        
// 数据列名
        private string fieldName;
      
        
// 控件值属性
        private PropertyInfo valueProperty;

        
// 控件
        private Control oCtrl;

        
/**//// <summary>
        
/// 构造方法
        
/// </summary>
        
/// <param name="oControl">源控件</param>
        
/// <param name="ValueName">控件值属性的名称</param>
        
/// <param name="strFieldName">数据列名</param>
        public DataGridTemplate(Control oControl, string ValueName, string strFieldName)
        {
            Type oType 
= oControl.GetType();
            
//PropertyInfo oPropertyInfo = oType.GetProperty(ValueName);
            valueProperty = oType.GetProperty(ValueName);
            oCtrl         
= oControl;
            fieldName     
= strFieldName;          
        }
           
        
/**//// <summary>
        
/// 实现ITemplate的InstantiateIn方法
        
/// </summary>
        
/// <param name="container">控件容器</param>
        public void InstantiateIn(System.Web.UI.Control container)
        {
            Control tmpCtrl 
=  ControlClone(oCtrl);  
            tmpCtrl.DataBinding 
+= new EventHandler(ControlTemplate_DataBinding);
            container.Controls.Add(tmpCtrl);
        }
            
        
/**//// <summary>
        
/// 绑定事件处理
        
/// </summary>
        
/// <param name="sender"></param>
        
/// <param name="e"></param>
        private void ControlTemplate_DataBinding(object sender, System.EventArgs e)
        {
            Control tmpCtrl;
            tmpCtrl 
= (Control)sender;          
            DataGridItem container 
= (DataGridItem) tmpCtrl.NamingContainer; 
            
try
            {
                
string s = valueProperty.GetValue(tmpCtrl, null).ToString();
                s 
+= DataBinder.Eval(container.DataItem, fieldName);
                valueProperty.SetValue(tmpCtrl , s ,
null);                
            }
            
catch
            {
            }
        }

        
/**//// <summary>
        
/// 复制控件
        
/// </summary>
        
/// <param name="oSource">源控件</param>
        
/// <returns></returns>
        private Control ControlClone(Control oSource)
        {    
            
//创建复制品
            Control oTarget = (Control)System.Activator.CreateInstance( oSource.GetType() );
            
            
//检查控件是否列表控件
            ListControl oListControl = oSource as ListControl ;
            
if (oListControl != null// 是列表控件
            {
                
foreach (ListItem oItem in oListControl.Items) // 复制列表项
                {
                    ((ListControl)oTarget).Items.Add(
new ListItem(oItem.Text , oItem.Value));
                }
            }
                
            
//将源对象的属性复制给复制品
            Type oType = oSource.GetType() ;
            
// 复制控件属性
            foreach (PropertyInfo oProperty in oType.GetProperties(BindingFlags.Instance| BindingFlags.Public ))
            {
                
try
                {
                    
object oData = oProperty.GetValue(oSource, null);
                  
                    oProperty.SetValue(oTarget , oData ,
null);
                }
                
catch{}
            }
            

            
return oTarget;
        }
    }

现在就可以动态创建模板列了:
TemplateColumn tc;

tc 
= new TemplateColumn();
tc.HeaderText 
= "列1";
tc.ItemTemplate 
= new DataGridTextBoxTemplate(ListItemType.Item, "列1");
dg.Columns.Add(tc);

tc 
= new TemplateColumn();
tc.HeaderText 
= "列2";
tc.ItemTemplate 
= new DataGridTextBoxTemplate(ListItemType.Item, "列2");
dg.Columns.Add(tc);