For various reasons, you might not know until run time what templates you
need or what text or controls should be in them. In that case, you need to be
able to create the templates dynamically (in code).
Note: You can also create templates as Web Forms user controls and bind
them dynamically to controls on your page. For details, see Creating a
Templated User Control.
You can create templates in code for all controls that use templates: the
DataList, Repeater, and DataGrid controls. For the DataGrid control, you use
templates to define columns instead of the row-like templates for the other
two controls.
Note: There are a few differences when creating template columns for the
DataGrid control. For details, see Creating Templates Programmatically in the
DataGrid Control.
Creating the Template Class
To create dynamic templates, you create a template class that you can then
instantiate when needed.
Note: For background on creating classes in Visual Basic .NET, see
Understanding Classes. For similar information for Visual C# .NET, see class.
To create a template class
Create a new class that implements the ITemplate interface of the
System.Web.UI namespace.
Optionally, pass into the class's constructor a value that the class can use
to determine what type of template to create (ItemTemplate,
AlternatingItemTemplate, and so on).
Tip A type-safe way to pass the template type to the constructor is to add
a parameter to the constructor with the type ListItemType. The ListItemType
enumeration defines the possible template types for the Repeater, DataList,
and DataGrid controls.
In the class, implement the InstantiateIn method (the only member of the
ITemplate interface). This method provides a way to insert an instance of
text and controls into the specified container.
In the InstantiateIn method, create the controls for the template item, set
their properties, and then add them to the parent's Controls collection. You
can access the parent control via the reference passed to the InstantiateIn
method.
Note You cannot directly add static text to the Controls collection, but
you can create controls like the Literal control or the LiteralControl
control, set their Text properties, and then add those controls to the parent
collection.
The following example illustrates a complete template class that displays
some static text ("Item number:") and a counter. The counter is maintained as
a shared or static value (depending on what language you are using) called
itemcount for the class and incremented each time a new item is created.
The class defines an explicit constructor that accepts a ListItemType
enumeration value to indicate what type of template is being created.
Depending on what type of template is being created, the code creates
different types of controls and adds them to the Controls collection of the
parent control. The end result is an HTML table with a different background
color for the alternating item template.
' Visual Basic
Private Class MyTemplate
Implements ITemplate
Shared itemcount As Integer = 0
Dim TemplateType As ListItemType
Sub New(ByVal type As ListItemType)
TemplateType = type
End Sub
Sub InstantiateIn(ByVal container As Control) _
Implements ITemplate.InstantiateIn
Dim lc As New Literal()
Select Case TemplateType
Case ListItemType.Header
lc.Text = "<TABLE border=1><TR><TH>Items</TH></TR>"
Case ListItemType.Item
lc.Text = "<TR><TD>Item number: " & itemcount.ToString _
& "</TD></TR>"
Case ListItemType.AlternatingItem
lc.Text = "<TR><TD bgcolor=lightblue>Item number: " _
& itemcount.ToString & "</TD></TR>"
Case ListItemType.Footer
lc.Text = "</TABLE>"
End Select
container.Controls.Add(lc)
itemcount += 1
End Sub
End Class
// C#
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;
}
}
Using the Dynamic Template
When you have a dynamic template available, you can instantiate it in code.
Note To work with a dynamic template as a column in a DataGrid control,
see Creating Templates Programmatically in the DataGrid Control.
To use a dynamic template
Create an instance of your dynamic template, passing it an item type value
if appropriate.
Assign the instance to one of the template properties of the Repeater or
DataList control: ItemTemplate, AlternatingItemTemplate, HeaderTemplate, and
so on.
The following example shows how to use the dynamic template with a Repeater
control. In this example, the templates are instantiated while the page is
being loaded and before the control is bound to its data source.
' Visual Basic
Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
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)
Repeater1.DataBind()
End Sub
// C#
private void Page_Load(object sender, System.EventArgs e)
{
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);
Repeater1.DataBind();
}
Adding Data Binding to Templates
There are various ways to get access to data from within a template class,
depending on how you have created the class. A good way is one in which the
page architecture itself implements data binding — when you add controls to
the template, you also add a handler for their DataBinding event. This event
will be raised after the template item has been created with all its
controls, and it provides you with an opportunity to fetch data and use it in
a control.
Note You cannot embed a data-binding expression as a string when creating
controls in the template, as you do when defining templates at design time,
because data-binding expressions are converted into code at a stage of page
processing that occurs before your template is created.
In the handler for the DataBinding event, you have an opportunity to
manipulate the contents of the control. Typically (but not necessarily), you
fetch data from somewhere and assign it to the control's Text property.
Note For background on data binding in Web Forms pages, see Web Forms Data
Binding.
To add data binding to a dynamic template, you must do the following:
Add a data-binding event handler to the controls you create in the template.
Create the handler that you are binding to. In the handler, get the data
that you want to bind to and assign it to the appropriate property of the
control being bound.
To add the data-binding event handler
After creating a control in the dynamic template, use standard commands to
bind the control's DataBinding event to a method that you will create later.
Note For details on how to add event handlers dynamically, see AddHandler
and RemoveHandler (for Visual Basic) and Events Tutorial (for Visual C#).
The following example shows code from the template class illustrating how
you can bind a newly created control to a method called
TemplateControl_DataBinding.
' Visual Basic
Dim lc As New Literal()
Case ListItemType.Item
lc.Text = "<TR><TD>"
AddHandler lc.DataBinding, AddressOf TemplateControl_DataBinding
// C#
Literal lc = new Literal();
case ListItemType.Item:
lc.Text = "<TR><TD>";
lc.DataBinding += new EventHandler(TemplateControl_DataBinding);
break;
Note that in this example, the text you add to the literal control's Text
property is different than in the previous example. It contains only the
beginning of the table row and cell for the item template. You will complete
the cell and row in the data-binding event handler.
The next step is to create the event handler that will be called when the
control is data bound.
To create the handler for the DataBinding event
Create a method that is part of your template class as a peer of the class's
other methods (such as InstantiateIn). The handler's name must match the name
you used when binding the event earlier. The method should have the following
signature:
' Visual Basic
Private Sub TemplateControl_DataBinding(ByVal sender As Object, _
ByVal e As System.EventArgs)
// C#
private void TemplateControl_DataBinding(object sender,
System.EventArgs e)
Get a reference to the DataItem object containing the data for the current
template item, by doing the following:
Get a reference to the template item. You create a variable to hold the
reference and then assign it the value you get from your control's
NamingContainer property.
Use that reference to get the naming container's (the template item's)
DataItem property.
Extract the individual data element (data column, for example) from the
DataItem object and use it to set a property of the control you are binding.
The following code illustrates one way to perform data binding within a
dynamic template. It shows a complete data-binding event handler for Literal
controls being created in a template for a Repeater control.
' Visual Basic
Private Sub TemplateControl_DataBinding(ByVal sender As Object, _
ByVal e As System.EventArgs)
Dim lc As Literal
lc = CType(sender, Literal)
Dim container As RepeaterItem
container = CType(lc.NamingContainer, RepeaterItem)
lc.Text &= DataBinder.Eval(container.DataItem, "CategoryName")
lc.Text &= "</TD></TR>"
End Sub
// C#
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>";
}
Note If you have multiple types of controls in your templates, you would
need to create a different data-binding event handler for each of the control
types
"Just Me" wrote:
Given a button name Btn_5 and Index=5
I want to do something like
dim zz as string = Btn_??Index??.Text
or given an array of buttons, do:
BtnArray(4)= Btn_??Index??
Not necessarily that simply, but is there a way I can create the name of a
variable at runtime?
Thanks