Creating Web Server Control Templates Dynamically

来源:百度文库 编辑:神马文学网 时间:2024/03/28 18:41:39
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, seeCreating 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, seeCreating 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, seeUnderstanding Classes. For similar information for Visual C# .NET, seeclass.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 typeListItemType. 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.
Copy Code
‘ 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 = "" Case ListItemType.Item lc.Text = "" Case ListItemType.AlternatingItem lc.Text = "" Case ListItemType.Footer lc.Text = "
Items
Item number: " & itemcount.ToString _ & "
Item number: " _ & itemcount.ToString & "
" 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 = ""; break; case ListItemType.Item: lc.Text = ""; break; case ListItemType.AlternatingItem: lc.Text = ""; break; case ListItemType.Footer: lc.Text = "
Items
Item number: " + itemcount.ToString() + "
Item number: " + itemcount.ToString() + "
"; 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, seeCreating 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.
Copy Code
‘ 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, seeWeb 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, seeAddHandler and RemoveHandler (for Visual Basic) andEvents 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.
Copy Code
‘ Visual Basic Dim lc As New Literal() Case ListItemType.Item lc.Text = "" AddHandler lc.DataBinding, AddressOf TemplateControl_DataBinding // C# Literal lc = new Literal(); case ListItemType.Item: lc.Text = ""; 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:
Copy Code
‘ 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.
Copy Code
‘ 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 &= "" 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 += ""; }
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.