Click here to Skip to main content
15,868,052 members
Articles / Web Development / ASP.NET
Article

Multi-field Grouping Repeater

Rate me:
Please Sign up or sign in to vote.
3.31/5 (6 votes)
13 Feb 20064 min read 167.7K   2K   47   51
Data repeater that can group by multiple database fields.

Introduction

After searching long and far for a Repeater control that would do exactly what I needed, I came up short. So, I did what any developer with too much time on their hands and no money to spend would do - I made my own.

Background

What really got me started on this was Rob van der Veer's article, "A Grouping Repeater Control for ASP.NET". I used his GroupingRepeater code as a starting point for my own code. Thanks Rob!

The problem

More often than not, I have found that I need a Repeater that is able to handle database results returned by queries with multiple join statements. We all know that a join statement can produce repetitive information. While Rob's article was a great starting point, his control had one major flaw: what if there is more than one "category" of unique repeating data?

The solution

In order to be able to implement the type of features, this control is much more complex. The way it works is this: instead of only one GroupTemplate, there are as many as needed. Much can be explained by seeing an example of what the templates would look like.

Note: The "HeaderTemplate" and "ItemTemplate" tags are incorrectly capitalized and/or spaced due to a conflict with the way this page is rendered.

ASP.NET
<uc1:GroupingRepeater ID="Items" Runat="Server">
     <headerTemplate>
         <table>
              <tr>
                  <td>Customer Name</td>
                  <td>Order History</td>
                  <td>Comments</td>
              </tr>
     </headerTemplate>
     
     < itemTemplate>
       <tr>
          <td><%# DataBinder.Eval(Container.DataItem, 
                                        "CustomerName") %></td>
          <td>
             <%# ((GroupingRepeater)Container.Parent).GroupData("OrderHistory")%>
          </td>
          <td>
            <%# ((GroupingRepeater)Container.Parent).GroupData("Comments") %>
          </td>
       </tr>
     < itemTemplate>
       
     <GroupTemplate>
          <div>
               <%# DataBinder.Eval(Container.DataItem, "OrderDate") %> - 
               <%# DataBinder.Eval(Container.DataItem, "OrderID") %>: 
               $<%# DataBinder.Eval(Container.DataItem, "OrderAmount") %>
          </div>
     </GroupTemplate>
     <GroupTemplate>
          <div>Posted by
               <%# DataBinder.Eval(Container.DataItem, "EmployeeName") %> on 
               <%# DataBinder.Eval(Container.DataItem, "CommentPostedDate") %>: 
               <%# DataBinder.Eval(Container.DataItem, "Comment") %>
          </div>
     </GroupTemplate>

     <GroupIdentifier Index="-1" Key="ItemTemplate" Field="ID" />
     <GroupIdentifier Index="0" Key="OrderHistory" Field="OrderID" />
     <GroupIdentifier Index="1" Key="Comments" Field="CommentID" />

     <SeparatorTemplate><tr><td 
         colspan="3"> </td></tr></SeparatorTemplate>
     <SeparatorTemplate><hr></SeparatorTemplate>
     
     <SeparatorIdentifier Index="0" Key="ItemTemplate" />
     <SeparatorIdentifier Index="1" Key="Comments" />

     <FooterTemplate></table></FooterTemplate>

</uc1:GroupingRepeater>

Now, some explanation

Since you've seen the example, now I'll explain how to set up your template code.

Templates

HeaderTemplate, FooterTemplate

These templates work just as they do in the standard ASP.NET Repeater.

AlternatingItemTemplate

This template is not supported in this version of the code. Sorry, I got lazy!

ItemTemplate

This template works mostly just like the ItemTemplate in the standard ASP.NET Repeater. The exception is that you have to identify the areas that will have the grouped items. You do this by using this code:

ASP.NET
<%# ((GroupingRepeater)Container.Parent).GroupData("GroupKey") %>

"GroupKey" should be replaced by whatever key you assign to that group in the corresponding GroupIdentifier, which I will explain below.

GroupTemplate

Use these templates to set up your various groups. These are used just like any ITemplate property, except that you can have as many as you like.

SeparatorTemplate

If you like, you can specify a SeparatorTemplate to be used between ItemTemplate items, and as many of your GroupTemplates as you like. If a SeparatorTemplate is specified for the ItemTemplate or a GroupTemplate, it will automatically be placed between each item.

Identifiers

The TemplateIdentifier control allows the GroupingRepeater to implement multiple templates by associating a developer-friendly "key" with the index location of the template.

GroupIdentifier

The GroupIdentifier templates are used to associate and identify which GroupTemplates are used where. For example:

HTML
<GroupIdentifier Index="1" Key="Comments" 
    Field="CommentID" EmptyGroupDataText="(No Comments)" />

This TemplateIdentifier would identify a GroupTemplate that will be referenced by the key "Comments", and is the second GroupTemplate listed in the repeater control (the "Index" is zero-based). The "Field" property specifies which field of the DataSource determines when a new group item should be created. If the value of this field is already present in the group items, the row will be skipped. The "EmptyGroupDataText" property specifies what text should be rendered in the event that there is no data to display. If this property is not specified, nothing is displayed in that situation.

Note: You must have a GroupIdentifier whose Index property is set to "-1" and whose Key property is set to "ItemTemplate". The Field property for this identifier determines when a new ItemTemplate item is to be created.

Note: You must specify a GroupIdentifier for each GroupTemplate specified!

SeparatorIdentifier

The SeparatorIdentifer works much like the GroupIdentifer, except that the Field and EmptyGroupDataText properties are not displayed. As with the GroupIdentifier, you must specify a SeparatorIdentifier for each SeparatorTemplate specified. However, you are not required to specify a SeparatorIdentifier for ItemTemplate.

And that's about it!

I hope you find this useful. Please note that I haven't done any terribly extensive debugging, but I will be updating the code as I make my own tweaks. Good luck, and enjoy!

Zounds, an update!

09 February 2006

Many people have posted requests in the comments for a working demo. Well, ask and ye shall receive - a demo is now available in the downloads section at the top of the page. It doesn't look too pretty, but it should give you a good idea of how this thing works and what it is capable of. Also, I've added an entire C#.NET project to the source file, including compiled binaries, to the source download. Enjoy!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralCan´t find an a DropDownList inside a grouptemplate [modified] Pin
renato.mgomes15-Nov-10 5:15
renato.mgomes15-Nov-10 5:15 
GeneralNullReference + postback Pin
Edgar_K10-Dec-09 18:29
Edgar_K10-Dec-09 18:29 
GeneralFails to subgroup past 1st nesting level Pin
kmesiab18-Oct-06 7:06
kmesiab18-Oct-06 7:06 
GeneralA Small modification Pin
sprunc5-Oct-06 11:10
sprunc5-Oct-06 11:10 
QuestionNullReference Exception in Postback Pin
maria del monte31-Mar-06 0:24
maria del monte31-Mar-06 0:24 
AnswerRe: NullReference Exception in Postback Pin
allUC25-Sep-06 6:08
allUC25-Sep-06 6:08 
GeneralRe: NullReference Exception in Postback -My Workaround Pin
allUC25-Sep-06 8:04
allUC25-Sep-06 8:04 
GeneralCan't get it working... Pin
Anonymous24-Aug-05 5:12
Anonymous24-Aug-05 5:12 
GeneralRe: Can't get it working... Pin
Daniel Schaffer13-Feb-06 4:30
Daniel Schaffer13-Feb-06 4:30 
GeneralCan't get it to work at all Pin
Alan-Orbis24-Aug-05 4:05
Alan-Orbis24-Aug-05 4:05 
GeneralRe: Can't get it to work at all Pin
Alan-Orbis25-Aug-05 1:47
Alan-Orbis25-Aug-05 1:47 
GeneralTake a look at the output HTML Pin
Daniel Schaffer25-Aug-05 3:18
Daniel Schaffer25-Aug-05 3:18 
GeneralRe: Take a look at the output HTML Pin
Alan-Orbis25-Aug-05 4:24
Alan-Orbis25-Aug-05 4:24 
GeneralThe way it works... Pin
Daniel Schaffer25-Aug-05 4:45
Daniel Schaffer25-Aug-05 4:45 
GeneralRe: The way it works... Pin
Alan-Orbis25-Aug-05 4:55
Alan-Orbis25-Aug-05 4:55 
GeneralSo let me get this straight.... Pin
Daniel Schaffer25-Aug-05 5:02
Daniel Schaffer25-Aug-05 5:02 
GeneralRe: So let me get this straight.... Pin
Alan-Orbis25-Aug-05 6:20
Alan-Orbis25-Aug-05 6:20 
GeneralDon't if this will work... Pin
Daniel Schaffer25-Aug-05 6:40
Daniel Schaffer25-Aug-05 6:40 
GeneralRe: Don't if this will work... Pin
Alan-Orbis25-Aug-05 6:44
Alan-Orbis25-Aug-05 6:44 
GeneralIf nothing else... Pin
Daniel Schaffer25-Aug-05 6:48
Daniel Schaffer25-Aug-05 6:48 
GeneralRe: If nothing else... [modified] Pin
kmesiab16-Oct-06 12:55
kmesiab16-Oct-06 12:55 
GeneralTrouble implementing repeater code Pin
Brandy Green10-Aug-05 4:35
Brandy Green10-Aug-05 4:35 
GeneralMissing Class Pin
Daniel Schaffer10-Aug-05 4:38
Daniel Schaffer10-Aug-05 4:38 
GeneralRe: Missing Class Pin
Brandy Green10-Aug-05 4:46
Brandy Green10-Aug-05 4:46 
GeneralJust noticed... Pin
Daniel Schaffer10-Aug-05 4:44
Daniel Schaffer10-Aug-05 4:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.