如何构建像DataBound模板化自定义ASP.NET服务器控件的GridView

时间:2010-04-13 18:24:14

标签: asp.net gridview custom-server-controls

我正在尝试开发一个非常简单的模板化自定义服务器控件,类似于GridView。基本上,我希望将控件添加到.aspx页面中,如下所示:

    <cc:SimpleGrid ID="SimpleGrid1" runat="server">
         <TemplatedColumn>ID: <%# Eval("ID") %></ TemplatedColumn>
         <TemplatedColumn>Name: <%# Eval("Name") %></ TemplatedColumn>
         <TemplatedColumn>Age: <%# Eval("Age") %></ TemplatedColumn>
    </cc:SimpleGrid>

并在提供以下数据源时:

    DataTable table = new DataTable();
    table.Columns.Add("ID", typeof(int));
    table.Columns.Add("Name", typeof(string));
    table.Columns.Add("Age", typeof(int));

    table.Rows.Add(1, "Bob", 35);
    table.Rows.Add(2, "Sam", 44);
    table.Rows.Add(3, "Ann", 26);

    SimpleGrid1.DataSource = table;
    SimpleGrid1.DataBind();

结果应该是像这样的HTML表格。

 -------------------------------
 | ID: 1 | Name: Bob | Age: 35 |
 -------------------------------
 | ID: 2 | Name: Sam | Age: 44 |
 -------------------------------
 | ID: 3 | Name: Ann | Age: 26 |
 -------------------------------

主要问题是我无法定义TemplatedColumn。当我试图这样做时......

    private ITemplate _TemplatedColumn;
    [PersistenceMode(PersistenceMode.InnerProperty)]
    [TemplateContainer(typeof(TemplatedColumnItem))]
    [TemplateInstance(TemplateInstance.Multiple)] 
    public ITemplate TemplatedColumn
    {
        get { return _TemplatedColumn; }
        set { _TemplatedColumn = value; }
    }

..然后在CreateChildControls中实例化模板我得到了以下结果,这不是我想要的:

 -----------
 | Age: 35 |
 -----------
 | Age: 44 |
 -----------
 | Age: 26 |
 -----------
  • 我知道我想要实现的目标是毫无意义的,我可以使用DataGrid来实现它,但是我给出了这个非常简单的例子,因为如果我知道如何做到这一点,我将能够开发出我需要的控件。谢谢。

3 个答案:

答案 0 :(得分:1)

看一下这篇文章:Building DataBound Templated Custom ASP.NET Server Controls

它已经很老了,但我猜它仍然有效。

答案 1 :(得分:0)

我遇到了和你一样的问题。

经过一番搜索,我找到了一种方法来做你想做的事。它并不完美,因为它需要为每个列定义一个控件+一个模板(你给出的例子直接定义了一个模板),但是它可以工作。

//define a new property "Columns" in the grid
//it will hold a collection of controls of type "TemplatedColumn"
public class Grid : WebControl
{
    private ColumnsCollection _columnsCollection;
    public virtual ColumnsCollection Columns
    {
        get
        {
            if (_columnsCollection == null)
               _columnsCollection = new ColumnsCollection();
            return _columnsCollection;
        }
    } 
}

//define ColumnsCollection class (must implement IList)
public class ColumnsCollection : List<TemplatedColumn>  { ... }

//define TemplatedColumn webcontrol (in this case, must have a template)
public TemplatedColumn : WebControl
{ 
    private ITemplate _Template;

    [...] //attributes
    public ITemplate Template
    {
        get { return _Template; }
        set { _Template = value; }
    }
}

然后你可以这样做:

   <cc:Grid runat="server">
     <Columns>
         <cc:TemplatedColumn runat="server">
            <Template>ID: <%# Eval("ID") %></Template>
         </cc:TemplatedColumn>
         <cc:TemplatedColumn runat="server">
            <Template>Name: <%# Eval("Name") %></Template>
         </cc:TemplatedColumn>
     <Columns>
   </cc:Grid>

答案 2 :(得分:-1)

我知道如何解决这个问题:

DataTable table = new DataTable();
table.Columns.Add("ID", typeof(int));
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Age", typeof(int));

table.Rows.Add(1, "Bob", 35);
table.Rows.Add(2, "Sam", 44);
table.Rows.Add(3, "Ann", 26);

SimpleGrid1.DataSource = table;
SimpleGrid1.DataBind();

到此:

-------------------------------
| ID: 1 | Name: Bob | Age: 35 |
-------------------------------
| ID: 2 | Name: Sam | Age: 44 |
-------------------------------
| ID: 3 | Name: Ann | Age: 26 |
-------------------------------

来自ITemplate:

public class CustomColumnDefiner : ITemplate { ...

为CustomColumnDefiner添加一个公共字段,用于列名和ListItemType。

在CustomColumnDefiner中覆盖此函数:

void ITemplate.InstantiateIn(System.Web.UI.Control container)

在InstantiateIn中,如果成员ListItemType是ListItemType.Item,请检查列名称。如果列名称为Age,则将传入标签的值编辑为“Age:”+传入值。它基本上是对列的每个单元格进行后处理,以添加“年龄:”部分。

在设置方面有一个这样的功能:

private static TemplateField GetTemplateColumn(string sColName)
    {
        TemplateField templateField = new TemplateField();

        templateField.HeaderTemplate = new CustomColumnDefiner(ListItemType.Header, sColName);
        templateField.ItemTemplate = new CustomColumnDefiner(ListItemType.Item, sColName);

        return templateField;
    }

然后在您的aspx页面代码后面。

myGridView.Columns.Add(GetTemplateColumn("Age"));

我已经使用这种方法将GridViews弯曲到我的意愿。它适用于从您的数据表转到您想要的html表。它是否适合您的整体解决方案我不知道。