How to build a GridView like DataBound Templated Custom ASP.NET Server Control
I am trying to develop a very simple templated custom server control that resembles GridView. Basically, I want the control to be added in the .aspx page like this:
<cc:SimpleGrid ID="SimpleGrid1" runat="server">
<TemplatedColumn>ID: <%# Eval("ID") %></ TemplatedColumn>
<TemplatedColumn>Name: <%# Eval("Name") %></ TemplatedColumn>
<TemplatedColumn>Age: <%# Eval("Age") %></ TemplatedColumn>
</cc:SimpleGrid>
and when providing the following datasource:
DataTable table = new DataTable();
table.Columns.Add("ID", typeof(int));
tabl开发者_如何转开发e.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();
the result should be a HTML table like this one.
-------------------------------
| ID: 1 | Name: Bob | Age: 35 |
-------------------------------
| ID: 2 | Name: Sam | Age: 44 |
-------------------------------
| ID: 3 | Name: Ann | Age: 26 |
-------------------------------
The main problem is that I cannot define the TemplatedColumn. When I tried to do it like this ...
private ITemplate _TemplatedColumn;
[PersistenceMode(PersistenceMode.InnerProperty)]
[TemplateContainer(typeof(TemplatedColumnItem))]
[TemplateInstance(TemplateInstance.Multiple)]
public ITemplate TemplatedColumn
{
get { return _TemplatedColumn; }
set { _TemplatedColumn = value; }
}
.. and subsequently instantiate the template in the CreateChildControls I got the following result which is not what I want:
-----------
| Age: 35 |
-----------
| Age: 44 |
-----------
| Age: 26 |
-----------
- I know that what I want to achieve is pointless and that I can use DataGrid to achieve it, but I am giving this very simple example because if I know how to do this I would be able to develop the control that I need. Thank you.
Have a look at this article : Building DataBound Templated Custom ASP.NET Server Controls
It's quite old, but I guess it's still valid.
I was facing same problem as you.
After some search, I found a way to do what you want. It's not perfect as it requires to define a control + a template for each column (example you give defines a template directly), but it works.
//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; }
}
}
Then you can do :
<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>
I know how to get you from this:
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();
to this:
-------------------------------
| ID: 1 | Name: Bob | Age: 35 |
-------------------------------
| ID: 2 | Name: Sam | Age: 44 |
-------------------------------
| ID: 3 | Name: Ann | Age: 26 |
-------------------------------
Derive from ITemplate:
public class CustomColumnDefiner : ITemplate { ...
Add a public field to CustomColumnDefiner for the column name and ListItemType.
override this function in CustomColumnDefiner:
void ITemplate.InstantiateIn(System.Web.UI.Control container)
In InstantiateIn, if the member ListItemType is ListItemType.Item, check the column name. If the column name is Age then edit the incoming label's value to be "Age : " + incoming value. It's basically post-processing each cell of the column to add the "Age :" part.
On the setup side there is a function like this:
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;
}
then in your aspx page code behind.
myGridView.Columns.Add(GetTemplateColumn("Age"));
I've used this method to bend GridViews to my will. It will work for going from your datatable to the html table you want. Whether it will fit into your overall solution I don't know.
精彩评论