Introduction
ASP.NET version 3.5 added two new data Web controls to the Toolbox: the ListView and DataPager. As discussed in the first installment of this article
series, Displaying Data with the ListView, the ListView control offers the same
built-in features found in the GridView, but much finer control over the rendered output. The ListView's output is defined using a variety of templates,
and we looked at examples using the control's LayoutTemplate and ItemTemplates. In particular, these examples used a LayoutTemplate that included a
placeholder for the ItemTemplate's rendered output.
The ItemTemplate is rendered for each record bound to the ListView control, and is typically referenced in the LayoutTemplate. This approach generates
the rendered markup defined in the LayoutTemplate, plus the rendered markup created by the ItemTemplate for each record. This works fine for simple
rendering scenarios, but in more complex scenarios we may need to render different formatting markup for different groups of records.
For example, imagine that we needed to display a set of records in a three-column HTML <table>. For each record we would want to
emit a table cell (<td>), but for every three records we would need to emit a new table row (<tr>).
Such customizations can be accomplished declaratively with the ListView control's includes GroupTemplate and GroupItemCount properties.
In this article we will see how to use the GroupTemplate and GroupItemCount properties to instruct the ListView control to render
different encasing markup for every n records. We will look at two demos: one that renders records into a series of ordered lists, and
another that illustrates how to display data in a multi-column table. Read on to learn more!
Grouping Basics
As we saw in the Displaying Data with the ListView article, the ListView control
contains two requisite templates: LayoutTemplate and ItemTemplate. The LayoutTemplate is rendered to generate the ListView control's markup and can contain
a reference to the ItemTemplate, which is used to render each record bound to the ListView control. The LayoutTemplate references the ItemTemplate through
a server-side control (such as the PlaceHolder control) whose ID is the same as the ListView's ItemPlaceholderID
property. (The ItemPlaceholderID property has a default value of "itemPlaceholder".)
Referencing the ItemTemplate directly from the LayoutTemplate works well if the encasing markup for each item is the same, but in several scenarios
different encasing markup may need to be introduced every n items. Such customization is possible by defining a
GroupTemplate and setting the
ListView control's GroupItemCount property
to n. Then, instead of referencing the ItemTemplate in the LayoutTemplate, have the LayoutTemplate reference the GroupTemplate, and the GroupTemplate
reference the ItemTemplate. Such a setup still has the ItemTemplate rendered for every record bound to the ListView control, but causes the
GroupTemplate to be rendered every GroupItemCount number of records.
To better understand how grouping with the ListView control works, let's take the first example we examined in the
Displaying Data with the ListView article and extend it to use grouping.
The first example illustrated how to display a set of records in an ordered list, and used the following declarative
markup for the ListView control:
The ListView control's declarative markup is nearly the same as in the previous article, but instead of the <ol> element being in
the LayoutTemplate, it has been moved to the GroupTemplate. The ItemTemplate has reamined the same. Note, however, that the LayoutTemplate still must
be present and now references the GroupLayout. Also note that instead of the default values for the group and item placeholders ("groupPlaceholder" and
"itemPlaceholder") I have explicitly changed these values through the ListView control's ItemPlaceHolderID
and GroupPlaceholderID properties.
Imagine that the above ListView is bound to an employees database table, and that in the ItemTemplate we were rendering the FullName
column within the <li> element. What would the ListView's rendered markup look like?
Well, the ListView would start by rendering it's LayoutTemplate:
It would then render its GroupTemplate for each group of three records bound to the ListView control. Assuming that there were eight
total employees, this would result in the following markup:
Displaying Data in a Multi-Column Table
Displaying records in a multi-column table is a very common scenario, and is one that requires rendering different formatting markup for groups of
records. Oftentimes, such formatting is achieved through the use of a multi-column HTML <table>. For example, to display a three-column
table, we would render three table cells (<td>) in each table row (<tr>), like so:
<tr>
<td>Record N - 2</td>
<td>Record N - 1</td>
<td>Record N</td>
</tr>
</table>
In order to generate such markup with a ListView control, we need to use a LayoutTemplate that renders the outer <table> and
</table> tags, a GroupTemplate that renders the table row elements, and an ItemTemplate that renders each table cell.
The following declarative markup illustrates how to display data in a three-column table:
The download available at the end of this article includes a demo that displays the records from the Northwind database's Products table
in a three-column table, which yields the following when viewed through a browser.
Conclusion
In this article we examined how to render output batched into a specified group size using the ListView control's GroupTemplate and GroupItemCount
property. This template and property are useful in scenarios where the formatting layout needs to change for every n rendered records, such as
when displaying a multi-column table. Prior to the ListView control, such grouping required the page developer to write code that would intelligently
inject additional formatting markup for every n records. But with the ListView control's GroupTemplate and GroupItemCount property,
group formatting is now possible entirely through declarative means.