Programming Microsoft ASP.NET 4 - Dino Esposito [257]
However, this doesn’t mean that your group templates must have a fixed layout and can’t be dynamically populated using data from its contained items. The ListView’s ItemDataBound event is the key to obtaining output such as that shown in Figure 11-8.
Figure 11-8. The header of each group is determined dynamically by looking at the bound contents.
To start out, let’s take a look at the overall layout template of the ListView control:
GroupItemCount="5" OnItemDataBound="ListView1_ItemDataBound">
The group template is made of a Label control followed by an
tag and the list of data items. Each bound item is expressed through an
private int lastGroup = -1;
protected void ListView1_ItemDataBound(object sender, ListViewItemEventArgs e)
{
// To assign the group a data-bound title, retrieve the data item first
if (e.Item.ItemType == ListViewItemType.DataItem)
{
var currentItem = (ListViewDataItem) e.Item;
CustomizeGroupHeader((ListView) sender, currentItem);
}
}
The ListViewItemEventArgs argument contains an Item property that refers to the item being bound to data. This item can be of a few types—InsertItem, EmptyItem, or DataItem. The list of feasible values is in the ListViewItemType enumerated type. In this case, we’re interested only in data items—that is, regular items showing some bound data.
To put your hands on the real data being bound to the item, you need to cast the ListView item to the ListViewDataItem type, from which you can access a number of data-related properties:
private void CustomizeGroupHeader(ListView root, ListViewDataItem currentItem)
{
// The type of the data item depends on the data you bound--in this case,
// a collection of Customer objects
var cust = (DAL.Customer) currentItem.DataItem;
// Get a ListViewContainer object--the container of the group template
Control container = currentItem.NamingContainer;
if (container == null)
return;
// Look up for a particular control in the group template--the Label
Label groupHeader = (Label)container.FindControl("groupHeader");
if (groupHeader == null)
return;
// Figure out the 0-based index of current group. Note that the display index
// refers to the index of the item being bound, not the group
int groupIndex = currentItem.DisplayIndex / root.GroupItemCount;
if (groupIndex != lastGroup)
{
// This is a new group
lastGroup = groupIndex;
// Update the UI
groupHeader.Text = String.Format("Group {0} starting with {1}",
groupIndex + 1,
cust.CompanyName.Substring(0, 1).ToUpper());
}
}
You first get a reference to the naming container of the item. This container is the wrapper control for the group template. By using the FindControl method, you gain access to the Label control in the group template. The final step entails determining the value for the Text property of the Label control.
As mentioned, the ListView control doesn’t provide any readymade information about groups. So you don’t know about the index of the current group. The DisplayIndex property tells you only the index of the item being processed. Because the size of each group is fixed—and is based on the GroupItemCount property—you can easily obtain the 0-based index of the current