Programming Microsoft ASP.NET 4 - Dino Esposito [118]
An ASP.NET control that can contain child controls and is at risk of having conflicting IDs should be created as a naming container—that is, it should implement the INamingContainer (marker) interface. A naming container has an effect on the default algorithm used for ID generation.
Note
A naming container is primarily a control that acts as a container for other controls. In doing so, the naming container generates a sort of virtual namespace so that ASP.NET roots the actual ID of contained controls in the ID of the naming container.
To fully understand the role and importance of naming containers, consider the following example. Imagine you have a composite control, such as a user control, that includes a child control like a button. Entirely wrapped by the user control, the button is not directly accessible by the page code and can’t be given a distinct and per-instance ID. In the end, the ID of the button is hard-coded in the outermost control that creates it.
What happens when two or more instances of the composite control are placed on a page? Are you going to have two button child controls with the same ID? This is exactly what will happen unless you configure the composite control to be a naming container. A naming container is taken seriously by ASP.NET when it generates IDs automatically to avoid conflicts.
To see the ASP.NET ID autogeneration mechanism in action, consider the following code fragment. It features an ASP.NET Repeater control—a data-bound control whose content consists of repeating the item template for each object in a bound collection. (Data binding is the topic of Chapter 10.)
<%# DataBinder.Eval(Container.DataItem, "CustomerID") %>
You populate the Repeater control using the following sample code:
protected void Page_Load(object sender, EventArgs e)
{
// Load some data into the Repeater
var customerIds = new Object[] {
new { CustomerID = "ALFKI" },
new { CustomerID = "ANATR" },
new { CustomerID = "BOTTM" }
};
Repeater1.DataSource = customerIds;
Repeater1.DataBind();
}
The Repeater then produces the HTML markup shown here:
- ALFKI
- ANATR
- BOTTM
The ’s ID is simply emitted as is for each data bound item. As a result, the page DOM will contain multiple elements with the same ID. This conflict violates the HTML standard but doesn’t prevent a successful page display. However, it will make it hard to script elements if you need to. In this example, though, the Repeater control doesn’t embed any other ASP.NET control. As a further step, let’s try adding some server controls, instead, in the repeatable template: <%# DataBinder.Eval(Container.DataItem, "CustomerID") %> Bound to the same data source as in the previous example, the Repeater control for any version of ASP.NET older than version 4 produces a slightly different markup: Note that if the ASPX markup is hosted by the content placeholder of a master page, the composed ID will be longer because it will be prefixed by the ID of the placeholder too: ctl00_MainContentPlaceholder_Repeater2_ctl00_Element In the client page, each tag now has its own unique ID, and client scripting is much easier. Now if you want to, say, render in blue and bold the element that contains ALFKI, you can add the following script. (The script assumes the jQuery library is being used. I’ll cover the jQuery library in Chapter