转自:http://www.cnblogs.com/guiliangfeng/archive/2009/04/19/1439235.html

很长一段时间中,不管是使用DataGrid 还是GridView都是通过拖放的方式。而这两天有个需求必须使用自定义的GridView,动态创建GridView的Columns,折腾了数小时,终于搞定,下面来说说具体的方法,希望能够帮助新手,也希望高手指点,毕竞我也够菜的;入正题:

一、来看看在VS2005自带的帮助文档中在Repeater使用动态创建的 的方法:

要创建动态模板,请创建以后需要时可实例化的模板类。

创建模板类

创建实现 System.Web.UI.ITemplate 接口的新类。

  • 您也可以将值传递到类的构造函数,类可以使用该值来确定要创建的模板类型(ItemTemplate、AlternatingItemTemplate 等)。

    将模板类型传递到构造函数的类型安全方法是向构造函数添加类型为 ListItemType 的参数。ListItemType 枚举为 Repeater、DataList 和其他控件定义可能的模板类型。

  • 在类中,实现 InstantiateIn 方法,该方法是 ITemplate 接口的成员。

    此方法提供将文本实例和控件实例插入指定容器的方法。

  • 在 InstantiateIn 方法中,为模板项创建控件,设置其属性,然后将它们添加到父级的 Controls 集合。

    您可以通过传递到 InstantiateIn 方法的引用访问父控件。

    不能直接向 Controls 集合添加静态文本,但可以创建类似 Literal 控件或 LiteralControl 控件的控件,设置它们的 Text 属性,然后向父集合添加这些控件。

    下面的代码示例阐释完整的模板类,该类显示某些静态文本(“Item number:”)和计数器。计数器是名为 itemcount 的静态值(在 Visual Basic 中为共享值),在每次创建新项时都会递增。该类定义一个接受 ListItemType 枚举值以指示所创建模板类型的显式构造函数。根据所创建的模板类型,代码创建不同类型的控件并将其添加到父控件的 Controls 集合。最终结果是一个 HTML 表,其中的交替项模板具有不同的背景色。

    public class MyTemplate : ITemplate
    {
    static int itemcount = 0 ;
    ListItemType templateType;

    public MyTemplate(ListItemType type)
    {
    templateType
    = type;
    }


    public void InstantiateIn(System.Web.UI.Control container)
    {
    Literal lc
    = new Literal();
    switch (templateType)
    {
    case ListItemType.Header:
    lc.Text
    = " <TABLE border=1><TR><TH>Items</TH></TR> " ;
    break ;
    case ListItemType.Item:
    lc.Text
    = " <TR><TD>Item number: " + itemcount.ToString() +
    " </TD></TR> " ;
    break ;
    case ListItemType.AlternatingItem:
    lc.Text
    = " <TR><TD bgcolor=lightblue>Item number: " +
    itemcount.ToString()
    + " </TD></TR> " ;
    break ;
    case ListItemType.Footer:
    lc.Text
    = " </TABLE> " ;
    break ;
    }

    container.Controls.Add(lc);
    itemcount
    += 1 ;
    }

    }

    Collapse 图像 使用动态模板

    有了可用的动态模板,就可以在代码中将其实例化了。

    创建动态模板

    创建动态模板的实例,如果合适的话,将一个项类型值传递给它。

  • 将该实例分配给模板化控件的模板属性之一,如 ItemTemplate、AlternatingItemTemplate 和 HeaderTemplate 属性。

    下面的代码示例演示如何与 Repeater 控件一起使用动态模板。在此示例中,在加载页时,而且是在控件绑定到数据源之前,将模板实例化。

    private void Page_Load( object sender, System.EventArgs e)
    {
    SqlConnection conn
    =
    new SqlConnection(ConfigurationManager.ConnectionStrings[ " Northwind " ].ConnectionString);

    SqlDataAdapter sqlDataAdapter1;
    DataSet dsCategories1;

    sqlDataAdapter1
    = new SqlDataAdapter( " SELECT CategoryID, CategoryName FROM Categories " , conn);
    dsCategories1
    = new DataSet();

    Repeater1.HeaderTemplate
    = new MyTemplate(ListItemType.Header);
    Repeater1.ItemTemplate
    = new MyTemplate(ListItemType.Item);
    Repeater1.AlternatingItemTemplate
    =
    new MyTemplate(ListItemType.AlternatingItem);
    Repeater1.FooterTemplate
    = new MyTemplate(ListItemType.Footer);
    sqlDataAdapter1.Fill(dsCategories1,
    " Categories " );
    Repeater1.DataSource
    = dsCategories1.Tables[ " Categories " ];
    Repeater1.DataBind();
    }

    Collapse 图像 向模板添加数据绑定

    根据创建类的方法,可以用多种方法访问模板类中的数据。一种方法是页框架自行实现数据绑定 - 当您向模板添加控件时,也会为这些控件的 DataBinding 事件添加处理程序。在创建了模板项及其所有控件后,会引发此事件,这样您就有机会获取数据并在控件中使用数据。

    case ListItemType.Item:

    lc.Text
    = " <TR><TD> " ;
    lc.DataBinding
    += new EventHandler(TemplateControl_DataBinding);
    break ;

    在上例中,您添加到文本控件的 Text 属性的文本不同于前一示例。该示例只包含了项模板的表行和单元格的开头。您将在数据绑定事件处理程序中填写单元格和行。

  • 下一步是创建事件处理程序,在控件处于数据绑定状态时将调用该事件处理程序。

    为 DataBinding 事件创建处理程序

    创建属于模板类的方法,它还是该类的其他方法(如 InstantiateIn)的对等方法。处理程序的名称必须与早期绑定事件时使用的名称相匹配。该方法应该具有以下签名:

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

    通过执行以下操作获取对包含数据的 DataItem 对象的引用:

    获取对模板项的引用。创建变量来保存该引用,然后将从控件的 NamingContainer 属性获取的值分配给它。

  • 使用该引用来获取命名容器的(模板项的) DataItem 属性。

  • 从 DataItem 对象提取单个数据元素(例如数据列),并使用它来设置您要绑定的控件的属性。

    下面的代码示例阐释在动态模板内执行数据绑定的一种方式。它演示了在 Repeater 控件的模板中创建的 Literal 控件的完整数据绑定事件处理程序。

    private void TemplateControl_DataBinding( object sender,
    System.EventArgs e)
    {

    Literal lc;

    lc
    = (Literal)sender;
    RepeaterItem container
    = (RepeaterItem)lc.NamingContainer;
    lc.Text
    += DataBinder.Eval(container.DataItem, " CategoryName " );
    lc.Text
    += " </TD></TR> " ;
    }

    如果在您的模板中具有多种类型的控件,您需要为每一种控件类型创建一个不同的数据绑定事件处理程序。

  • 二、在我自己的项目中使用的控件是GridView,动态模板列中使用的是LinkButton控件,创建的过程大概与上面相同,如下:

    创建模板类

    public class GaugeValueTemplate : ITemplate
    {
    #region ITemplate 成员

    public void InstantiateIn(Control container)
    {
    LinkButton lbGaugeMakeValue
    = new LinkButton();
    lbGaugeMakeValue.ID
    = " LB_GaugeMakeValue " ;
    lbGaugeMakeValue.DataBinding
    += new EventHandler(lbGaugeMakeValue_DataBinding);
    lbGaugeMakeValue.CommandName
    = " GaugeMakeValue " ;

    container.Controls.Add(lbGaugeMakeValue);
    }


    void lbGaugeMakeValue_DataBinding( object sender, EventArgs e)
    {
    LinkButton lbGaugeMakeValue
    = (LinkButton)sender;
    GridViewRow container
    = (GridViewRow)lbGaugeMakeValue.NamingContainer;

    // 绑定GaugeMakeValue字段的值
    lbGaugeMakeValue.Text = DataBinder.Eval(container.DataItem, " GaugeMakeValue " ).ToString();
    }


    #endregion

    }
    TemplateField GaugeMakeValueColumn = new TemplateField();
    GaugeMakeValueColumn.HeaderText
    = " 指标制定值 " ;
    GaugeMakeValueColumn.ItemTemplate
    = new GaugeValueTemplate();

    从这里可以看出GridView与Repeater控件中的区别在于:

    Repeater:RepeaerItem container = (RepeaterItem)lc.NamingContainer;
    lc.Text += DataBinder.Eval(container.DataItem, "CategoryName");

    GridView:GridViewRow container = (GridViewRow)lbGaugeMakeValue.NamingContainer;

    // 绑定GaugeMakeValue字段的值
    lbGaugeMakeValue.Text = DataBinder.Eval(container.DataItem, " GaugeMakeValue " ).ToString();

    三、关于DataGrid的方法,可参见 http://www.cnblogs.com/lovecherry/archive/2005/03/25/125526.html