Building a grouping Grid with GridView and ASP.NET AJAX toolkit CollapsiblePanel

by mosessaur 2/24/2008 2:00:44 AM

I admit, Matt Berseth is really inspiring me! Few days ago I pass through 2 of his great posts:

The first one is pure design tips one which I used for making good presentation of my demo here. The 2nd post is actually the idea.

Here I'll do the same idea Matt presented in his post, but I'll user ASP.NET 2.0 simple stuff plus ASP.NET AJAX Toolkit CollapsiblePanel control.It is required that you have ASP.NET AJAX Extensions installed to be able to run the sample code.

I'll not go through the presentation tips mentioned in Matt's post, I'll just show my technique to implement grouping idea with GridViews and CollapsiblePanel along with SqlDataSource which of course can be replaced with ObjectDataSource. I should mention that I'm using same style sheets provided in Matt's sample code along with images [View Demo].

Bellow is a screenshot of a running sample:
Collapsible Panel

The whole group is wrapped inside a ComponentArt like design:

   1: <div id="dlg" class="dialog" style="width: 700px">
   2:     <div class="header" style="cursor: default">
   3:         <div class="outer">
   4:             <div class="inner">
   5:                 <div class="content">
   6:                     <h2>
   7:                         Northwind: Orders By Customer</h2>
   8:                 </div>
   9:             </div>
  10:         </div>
  11:     </div>
  12:     <div class="body">
  13:         <div class="outer">
  14:             <div class="inner">
  15:                 <div class="content">
  16:                     <!-- My Code Goes Here -->
  17:                 </div>
  18:             </div>
  19:         </div>
  20:     </div>
  21:     <div class="footer">
  22:         <div class="outer">
  23:             <div class="inner">
  24:                 <div class="content">
  25:                 </div>
  26:             </div>
  27:         </div>
  28:     </div>
  29: </div>

The grouping will display orders by customer from Northwind database. Bellow is the SqlDataSource code for selecting Customers "sqlDsCustomers":

   1: <asp:SqlDataSource ID="sqlDsCustomers" runat="server" ConnectionString="<%$ ConnectionStrings:Northwind %>"
   2:     SelectCommand="SELECT [Customers].[CustomerID], [Customers].[CompanyName], COUNT([OrderID]) TotalOrders
   3:                     FROM [Customers] INNER JOIN [Orders] ON [Customers].[CustomerID]=[Orders].[CustomerID]
   4:                     Group By [Customers].[CustomerID], [Customers].[CompanyName]">
   5: </asp:SqlDataSource>

Now simply I can display my master data (grouping) which will display CustomerID with total number of orders he made:

   1: <asp:Panel CssClass="grid" ID="pnlCust" runat="server">
   2:     <asp:UpdatePanel ID="pnlUpdate" runat="server">
   3:         <ContentTemplate>
   4:             <asp:GridView Width="100%" AllowPaging="True" ID="gvCustomers" AutoGenerateColumns="False"
   5:                 DataSourceID="sqlDsCustomers" runat="server" ShowHeader="False" OnRowCreated="gvCustomers_RowCreated">
   6:                 <Columns>
   7:                     <asp:TemplateField>
   8:                         <ItemTemplate>
   9:                             <asp:Panel CssClass="group" ID="pnlCustomer" runat="server">
  10:                                 <asp:Image ID="imgCollapsible" CssClass="first" ImageUrl="~/Assets/img/plus.png"
  11:                                     Style="margin-right: 5px;" runat="server" />
  12:                                 <span class="header"> <%#Eval("CustomerID")%>: <%#Eval("CompanyName")%>(<%#Eval("TotalOrders")%>Orders)</span>
  13:                             </asp:Panel> <!-- Nested GridView And CollapsibalePanel will placed bellow this line -->
  14:                         </ItemTemplate>
  15:                     </asp:TemplateField>
  16:                 </Columns>
  17:             </asp:GridView>
  18:         </ContentTemplate>
  19:     </asp:UpdatePanel>
  20: </asp:Panel>

This will simply display something like this:
CollapsiblePanelDemo2

Note that the GridView is wrapped inside an ASP.NET Panel control. This is actually important when we start to work with CollapsiblePanel extender.

As we want to implement the grouped data of orders. We will add a nested GridView with its own SqlDataSource. Bellow is a the SqlDataSource for the nested GridView that will display customer orders "sqlDsOrders":

   1: <asp:SqlDataSource ID="sqlDsOrders" runat="server" ConnectionString="<%$ ConnectionStrings:Northwind %>"
   2:     SelectCommand="SELECT [OrderID], [OrderDate], [RequiredDate], [Freight], [ShippedDate] FROM [Orders] WHERE ([CustomerID] = @CustomerID)">
   3:     <SelectParameters>
   4:         <asp:Parameter Name="CustomerID" Type="String" DefaultValue="" />
   5:     </SelectParameters>
   6: </asp:SqlDataSource>
This SqlDataSource is placed inside the ItemTemplate of the master GridView. It is important to note that this SqlDataSource accepts a CustomerID as parameter. To provide this parameter value, we should handle RowCreated Event of the master GridView:
   1: protected void gvCustomers_RowCreated(object sender, GridViewRowEventArgs e)
   2: {
   3:     if (e.Row.RowType == DataControlRowType.DataRow)
   4:     {
   5:         SqlDataSource ctrl = e.Row.FindControl("sqlDsOrders") as SqlDataSource;
   6:         if (ctrl != null && e.Row.DataItem != null)
   7:         {
   8:             ctrl.SelectParameters["CustomerID"].DefaultValue = 
   9:                                ((DataRowView)e.Row.DataItem)["CustomerID"].ToString();
  10:         }
  11:     }
  12: }
Now time to place child nested GridView which will be attached to the "sqlDsOrders". Of course as a nested GridView it will be place just inside the ItemTemplate of the master GridView TemplateField:
   1: <asp:Panel Style="margin-left: 20px; margin-right: 20px" ID="pnlOrders" runat="server">
   2:     <asp:GridView AutoGenerateColumns="false" CssClass="grid" ID="gvOrders" DataSourceID="sqlDsOrders"
   3:         runat="server" ShowHeader="true" EnableViewState="false">
   4:         <RowStyle CssClass="row" />
   5:         <AlternatingRowStyle CssClass="altrow" />
   6:         <Columns>
   7:             <asp:TemplateField ItemStyle-CssClass="rownum">
   8:                 <ItemTemplate><%Container.DataItemIndex + 1%></ItemTemplate>
   9:             </asp:TemplateField>
  10:             <asp:BoundField HeaderText="Order ID" DataField="OrderID" ItemStyle-Width="80px" />
  11:             <asp:BoundField HeaderText="Date Ordered" DataField="OrderDate" DataFormatString="{0:MM/dd/yyyy}"
  12:                 ItemStyle-Width="100px" />
  13:             <asp:BoundField HeaderText="Date Required" DataField="RequiredDate" DataFormatString="{0:MM/dd/yyyy}"
  14:                 ItemStyle-Width="110px" />
  15:             <asp:BoundField HeaderText="Freight" DataField="Freight" DataFormatString="{0:c}"
  16:                 ItemStyle-Width="50px" ItemStyle-HorizontalAlign="Right" />
  17:             <asp:BoundField HeaderText="Date Shipped" DataField="ShippedDate" DataFormatString="{0:MM/dd/yyyy}"
  18:                 ItemStyle-Width="100px" />
  19:         </Columns>
  20:     </asp:GridView>
  21: </asp:Panel>
As you might noticed, this GridView is also wrapped in an ASP.NET Panel control. Now it is time to work with CollapsiblePanel.Just beneath the orders panel I'll place the CollapsiblePanel:
   1: <ajaxToolkit:CollapsiblePanelExtender ID="cpe" runat="Server" 
   2: TargetControlID="pnlOrders"
   3: ExpandControlID="pnlCustomer" CollapseControlID="pnlCustomer"
   4: CollapsedSize="0" Collapsed="True"
   5: AutoCollapse="False" AutoExpand="False" ScrollContents="false" 
   6: ImageControlID="imgCollapsible"
   7: ExpandedImage="~/Assets/img/minus.png" CollapsedImage="~/Assets/img/plus.png"
   8: ExpandDirection="Vertical" />

Now I'll explain the most important properties of the CollapsiblePanel that is used:

  • TargetControlID: Would be the ID of the ASP.NET Panel that contains the contents to be shown or hide. In our case would be the Orders list Panel "pnlOrders"
  • ExpandControlID and CollapseControlID: The ID of the ASP.NET Panel control that will control the expand (show) and collapse (hide) of the contents available in the TargetControlID. In our case would be the customer panel "pnlCust"
  • ImageControlID: The ID of an Image control where an icon indicating the collapsed status of the panel will be placed. The extender will replace the source of this Image with the CollapsedImage and ExpandedImage urls as appropriate. If the ExpandedText or CollapsedText properties are set, they are used as the alternate text for the image
  • ExpandedImage:The path to an image used by ImageControlID when the panel is collapsed
  • CollapsedImage:The path to an image used by ImageControlID when the panel is expanded.

Now when this run, it will display a collapsed list of customers. when you click on the customer it will expand and show list of orders made by that customer.

You can refer to the posted mentioned above for more design and presentation tips. Also the code of this sample is available to download.

Download sample code (291.25 kb) -AjaxControlToolkit v1.0.10920.0 included-

kick it on DotNetKicks.com

Currently rated 4.7 by 3 people

  • Currently 4.666667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

ASP.NET | ASP.NET AJAX | Client Side

Comments

2/18/2008 6:36:46 AM

Josh Stodola

I stumbled upon this blog today, and I remember you from the ASP.NET forums. Subscribed!

Josh Stodola us

2/18/2008 4:53:42 PM

mosessaur

Thank you Josh, of course I do know you well too. And was keeping visiting your blog and amazed with your own blog engine too. Thanks for the visit

mosessaur eg

2/23/2008 7:49:04 PM

Ustes G

I have tried to implement this same concept about 1 month ago, the problem I had was that my data was huge (100k rows), do you see any performance issues?

Ustes G us

2/24/2008 6:04:35 AM

mosessaur

Yes. But only if you are displaying too much data at the same page of the gird. That would cause a performance issue on the client browser, and in fact, during Callbacks of update panel if you use one.
But it depends on the browser, you’ll notice that Opera is performance a bit faster I guess

mosessaur eg

2/25/2008 12:15:20 PM

Ustes G

So how would you implement the nested grid scenario for large sets of data,that you can't page with a stored proc...? I am facing this situation now and just want to see how somebody else would go about it.

Ustes G us

2/26/2008 4:25:31 AM

mosessaur

Well, Myself I do paging through stored procedure, and if the procedure doesn't support paging, I redevelop it to make it support paging. So my Grid Page should display max of 15 rows. and in most cases I do not make paging in the sub one; not too much rows already, however if they contain too much rows, I'll do paging on them too.
But what do you mean you cannot page using stored procedure?!!
Anyway Check out this link:
www.c-sharpcorner.com/.../custompaging.aspx

mosessaur eg

3/5/2008 6:53:51 AM

Rob

I've been trying to replicate what you've done, but even though the code I'm using is very close to yours only the first of the collapsible panel's is working. Did you come across this when you were trying yours?

Rob gb

3/5/2008 7:02:20 AM

mosessaur

No, I didn't face such case while building this sample!
Why don't you check your CollapsiblePanel settings?
Or post your code somewhere so I can look at it, because if your code is similar to mine it should work.

mosessaur eg

3/6/2008 7:36:43 AM

Rob

I've already posted the code to here: http://forums.asp.net/t/1232627.aspx
I'm hoping it's one of those things where I've just missed the obvious. Maybe I'll spot it with a fresh head this morning.

Thanks for your help.

Rob gb

3/7/2008 3:55:15 AM

mosessaur

I see no issue in your code, but I'd like to ask something, do you notice that the image (collapsible image) change when you click on each group header?!

Because I guess it is data issue, I mean only first recode has details data that is rendered! Where is your data sources in the code?!

mosessaur eg

4/8/2008 1:30:15 PM

jaydev

Hi,
Again on performance!! Is there any way to populate the child data (I mean Order data) on the expand time (on the click of + sign), rather than initial load itself? It will increase the performance right?? Any suggestion or guidelines to achieve this will be appreciated

jaydev us

4/9/2008 9:01:13 AM

mosessaur

Yes Jaydev, that is possible! but it might needs few adjustments, and build another better solution. I guess I'll try to apply that soon

mosessaur eg

4/20/2008 11:08:03 AM

soohyung

Quick question for you. I am trying to set Pagesize of gridview to 20 instead of 10. I thought the panel automatically change there size, but it doesn't. Because I am not good at dealing with css, can you please tell me which part do I have to change for displaying 20 records per page. thanks.

soohyung us

4/22/2008 9:38:26 AM

mosessaur

Sorry for my late response,
Which panel do you mean exactly?! and I've changed the size to 20 and the page still looks fine!!
The nested panel will not be affected by page size

mosessaur eg

4/30/2008 1:33:53 PM

Rino

Hi,
very good...
But, i added a button for submit varius information.
When the page is reloaded, the CollapsiblePanel does not work.
Do you help me?

Thk.
Rino

Rino

4/30/2008 11:04:11 PM

mosessaur

Hey Rino,
Could you submit your code to me!

mosessaur eg

4/30/2008 11:38:13 PM

Rino

I sent you an email.
Thanks.

Rino

Rino

5/17/2008 10:29:21 AM

Jayashree Chakraborty

Is it possible for u to give me the source code of CollapsiblePanel in Zip format.
Thanks
Jayashree

Jayashree Chakraborty in

5/18/2008 1:52:06 PM

mosessaur

Hey Jayashree, here is the link to download in ZIP format
mosesofegypt.net/file.axd

mosessaur eg

6/23/2008 3:15:26 PM

Luis

Hi!I found this article very useful! I thought this can't be done in asp 2.0 but u saved my day.
Did you build another solution that populates data on the expand time?
Thanks n grats!

Luis pe

6/24/2008 7:32:00 PM

Hans Sissing

Hi Muhammad,

I Implemented a master details view using the ListView (framework 3.5), where edititng the detail is key.
I ran into your blog and with a little tweak is works fine!
Unlike what Dino Esposito demos on msdn (see msdn.microsoft.com/en-us/magazine/cc500643.aspx), with this technique i'm fully capable of implementing updating and inserting too! (He binds the datasource for the default view dynamically).
Great job!

Thanks,

- Hans Sissing.

Hans Sissing nl

6/25/2008 11:37:04 PM

mosessaur

@luis: Thank you Luis, Actually I didn't yet try to make on demand loading using ASP.NE AJAX Control Toolkit CollapsiblePanel. But I have a plan to try it, but not sure if it will work or not.
I recommend that you checkout my other post mosesofegypt.net/.../...own-Using-jQuery-AJAX.aspx
It contain the feature you wish to implement, but using jQuery not AJAXControlToolKit.

mosessaur eg

6/25/2008 11:39:32 PM

mosessaur

Hans, Thank you Hans, and I wish if you could send me your code, I would like to see what you have done! Because I think I might run into similar case and I don't wish to do from beginning Smile .
Good luck and thank you once again.

mosessaur eg

Add comment


(Will show your Gravatar icon)  

  Country flag

biuquote
  • Comment
  • Preview
Loading



Powered by BlogEngine.NET 1.4.0.0
Theme by Mads Kristensen

About the author

Name of author
mosesofegypt logo
Muhammad M. Mosa Soliman
Software Engineer.
MCT, MCSD.NET,
MCTS: .Net 2.0 Web, Windows, Distributed Applications
MCTS: WSS 3.0, MOSS 2007 Configuration & App Dev
MCPD: Enterprise Application Developer

E-mail me Send mail | Live Space My Live Space


Calendar

<<  July 2008  >>
MoTuWeThFrSaSu
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

View posts in large calendar

Recent Comments

Comment RSS

Community Credit

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008