Programming Microsoft ASP.NET 4 - Dino Esposito [288]
public class TitleTemplateContainer : WebControl, INamingContainer
{
private BarChart _parent;
public TitleTemplateContainer(BarChart parent)
{
_parent = parent;
}
public string Title
{
get { return _parent.Title; }
}
public string SubTitle
{
get { return _parent.SubTitle; }
}
public BarChart BarChart
{
get { return _parent; }
}
}
Once again, be sure to note that there are no constraints or special guidelines to influence the set of members of the class. The class needs to have a reference to the parent control—the BarChart in this case. Normally, you create this class for a particular control (or set of controls) and don’t reuse it beyond that. It is up to you to expose the parent control through a direct property (BarChart in the preceding code) or filter the control’s programming interface with a subset of properties (for example, Title and SubTitle). You can also do both things.
The programming interface of the template container class is important because it defines the information that page authors have access to when creating a template for the property. The template container is made accessible through the Container property.
Setting a Template Property
You can use any combination of controls and literals to populate a template. To access external information, though, you need to use data-bound expressions. Here’s an example:
<%# Container.Title %>
The code snippet demonstrates a BarChart title that displays an image in addition to the text set through the Title property. Here’s another example:
<%# Container.Title %> (<%# DateTime.Now.ToString() %>)
Figure 12-6 shows a templated title item where the originally set Title property is displayed side by side with the current time. The current time is rendered with a smaller font and within parentheses.
Figure 12-6. A BarChart control with a templated title.
Note that any style attributes set through the TitleStyle property are maintained in the template.
The Container keyword references an instance of the template container type. You use the Container keyword to access any control properties exposed through the template container class. Nonstatic information requires a <%# … %> data-bound expression, just like in the templates of ASP.NET built-in controls.
Rendering a Template
So far you’ve seen how to define a template property in a server control. But what other changes to the code are required to host a template? In summary, to define a template property you need to do the following:
Define a property of type ITemplate, and use a private variable as its storage medium.
Decorate the property with the PersistenceMode attribute.
Define a template container class.
Decorate the property with the TemplateContainer attribute.
These steps define only the public interface of the template; more is needed to embed the template in the control’s hierarchy. In particular, you need to tweak the code that creates the portion of the control tree where you want the template to display. For example, the TitleTemplate property refers to the title item; so the internal method to modify is CreateTitle. Here’s the updated version:
private void CreateTitle(Table t)
{
// Create the table row
var item = new BarChartItem(BarChartItemType.Title);
t.Rows.Add(item);
// Add the title cell
var cell = new TableCell();
cell.ColumnSpan = BarChart.ColumnsCount;
item.Cells.Add(cell);
// Decide between plain string and template
if (TitleTemplate != null)
{
_titleTemplateContainer = new TitleTemplateContainer(this);
TitleTemplate.InstantiateIn(_titleTemplateContainer);
cell.Controls.Add(_titleTemplateContainer);
}
else
cell.Text = Title;
// Must call DataBind to enable #-expression on templates
item.DataBind();
}
You check