Master\Detail with CollapsiblePanelExtender and edit detail with HoverMenuExtender using GridView

by mosessaur| 08 September 2008| 10 Comments

Last year, Matt posted a cool post about . Last month I got an e-mail from Justin Riggs, he was trying to combine to things. The usage of HoverMenuExtender as described in Matt's post, and the I posted about few months ago.

He already made the sample which ease the job for me in this post, but he had and issue that the functionality wasn't work properly. So I fixed that and thought to share it here in case anyone would love to apply same feature. You can view demo here.

It is a must that you return to by Matt, and Building a grouping Grid with GridView and ASP.NET AJAX toolkit CollapsiblePanel by me before you go a head in this post.

screen01 screen02

Performance Notes:

You'll notice performance issue with sample. The returns actually for many reasons such as the dependency javascript files that will be downloaded for both CollapsiblePanelExtender and HoverMenuExtender. Beside the usage of Nested UpdatePanels as you'll see later.

Nested UpdatePanels with Nested GridViews:

Before we go further, I also recommend to have a look Matt's post, In-Depth: The UpdatePanel ASP.NET AJAX Server Control: Triggers and UpdateMode.

I had to work with Nested UpdatePanels this time. It is just on Parent root UpdatePanel, and many child UpdatePanel underneath it. Below is a demonstration code for the structure of the Nested UpdatePanels with Nested GridViews.

<asp:UpdatePanel ID="pnlUpdateParent" UpdateMode="Conditional" 
	ChildrenAsTriggers="false" runat="server">
	<Triggers>
		<asp:AsyncPostBackTrigger ControlID="gvCustomers"
				 EventName="PageIndexChanged" />
	</Triggers>
	<ContentTemplate>
		<asp:GridView ID="gvCustomers" ....>
			<Columns>
				<asp:TemplateField>
					<ItemTemplate>
						<asp:UpdatePanel ID="pnlUpdateChild" 
							UpdateMode="Conditional" runat="server">
							<ContentTemplate>
								<asp:GridView ID="gvOrders" ....>

								</asp:GridView>
							</ContentTemplate>
						</asp:UpdatePanel>
					</ItemTemplate>
				</asp:TemplateField>
			</Columns>
		</asp:GridView>
	</ContentTemplate>
</asp:UpdatePanel>
Few things to note here. The Parent Panel "pnlUpdateParent" UpdateMode is set to Conditional, and ChildrenAsTriggers is set to false. This is very important, because the Children GridViews will raise postback triggers, and that will cause the whole UpdatePanel to be updated and I don't want that. I just want the child GridView that caused the postback to be updated, while the parent GridView remain silent.

Next you'll notice Triggers tag. Yes, I wanted the Parent UpdatePanel to be only updated when the Parent GridView raises PageIndexChanged Event. that means only upon paging.

Details GridView:

Most of the work has been made on the child GridView. To know more on how to set up the HoverMenuExtender, you'll need to return to Matt's post as I mentioned earlier. Below I am going to show how to handle GridView command events.

Here is the important ASPX code snippet in child GridView declaration:

<asp:GridView ID="gvOrders" 
	AutoGenerateColumns="False" 
	DataKeyNames="OrderID"
	CssClass="grid" 
	DataSourceID="sqlDsOrders"
	runat="server"
	OnRowCreated="gvOrders_RowCreated"
	OnRowEditing="gvOrders_RowEditing"
	OnRowCommand="gvOrders_RowCommand">
	.....
</asp:GridView>
Of course the "sqlDsOrders" SqlDataSource has update and delete statement defined. All columns in this GridView are read only except one column. I didn't show them here to save the size of this post. As you can see I declared 3 Event Handlers here:

  • OnRowCreated: used to initialize HoverMenuExtender. Return to Matt's post.
  • OnRowEditing: used to specifying current editing row.
  • OnRowComman: used to specify select parameter value of the SqlDataSource.

It worth to mention that OnRowComman event will be fired and executed every time any command is triggered. And will be fired first and before any other command event fired.

protected void gvOrders_RowCommand(object s, GridViewCommandEventArgs e)
{
    //CustomerID is stored as event Commend Argument
    string customerId = (string)e.CommandArgument;
    GridView orders = (GridView)s;
    Control parent = orders.Parent.Parent;
    //Find SqlDataSource
    SqlDataSource src = (SqlDataSource)parent.FindControl("sqlDsOrders");
    //Set select parameter value.
    src.SelectParameters[0].DefaultValue = customerId;
}
protected void gvOrders_RowEditing(object s, GridViewEditEventArgs e)
{
    GridView orders = (GridView)s;
    orders.EditIndex = e.NewEditIndex;
    orders.DataBind();
}
To use HoverMenuExtender as described in Matt's post, a GridView custom TemplateField is used. For the command buttons (LinkButton) that are used as custom GridView commands, I added a CommandArgument with CustomerID. As shown in the code snippet above, this CommandArgument is used to set the value of the SqlDataSource select parameter.
<asp:TemplateField HeaderStyle-Width="0px" 
	ItemStyle-Width="0px" ShowHeader="false">
    <ItemTemplate>
        <asp:Panel ID="popupMenu" runat="server" Style="display: none">
            <div style="border: 1px outset white; padding: 2px;">
                <div>
                    <asp:LinkButton ID="lnkButtonEdit" runat="server" 
                        CommandArgument='<%#Eval("CustomerID")%>' 
                        CommandName="Edit" Text="Edit" />
                </div>
                <div>
                    <asp:LinkButton ID="lnkButtonDelete" runat="server" 
                        Enabled="false"
                        CommandArgument='<%#Eval("CustomerID")%>' 
                        CommandName="Delete" Text="Delete" />
                </div>
            </div>
        </asp:Panel>
        <ajaxToolkit:HoverMenuExtender ID="hoverMenu" 
            runat="server" HoverCssClass="popupHover" 
            PopDelay="300" PopupControlID="PopupMenu" 
            PopupPosition="Right" TargetControlID="PopupMenu" />
    </ItemTemplate>
    <EditItemTemplate>
        <asp:Panel ID="popupMenu" runat="server">
            <div style="border: 1px outset white; padding: 2px;">
                <div>
                    <asp:LinkButton ID="lnkButtonUpdate" runat="server" 
                        CommandArgument='<%#Eval("CustomerID")%>' 
                        CommandName="Update" Text="Update" />
                </div>
                <div>
                    <asp:LinkButton ID="lnkButtonCancel" runat="server" 
                        CommandArgument='<%#Eval("CustomerID")%>' 
                        CommandName="Cancel" Text="Cancel" />
                </div>
            </div>
        </asp:Panel>
        <ajaxToolkit:HoverMenuExtender ID="hoverMenu" 
            runat="server" HoverCssClass="popupHover" 
            PopDelay="300" PopupControlID="PopupMenu" 
            PopupPosition="Right" TargetControlID="PopupMenu" />
    </EditItemTemplate>
    <HeaderStyle Width="0px" />
    <ItemStyle Width="0px" />
</asp:TemplateField>

Conclusion:

You have to be aware of the performance issue of the GUI when applying this feature. You'll notice that when you run the sample of view the demo. However you can utilize it by using it where and when appropriate. Or maybe use it with jQuery; by modifying a similar sample that uses jQuery for Master\Details drill down. Or maybe rebuild the whole thing using jQuery :O) would save you some bandwidth.

I hope that you enjoyed it.

You can download the sample here, or View demo.

kick it on DotNetKicks.com

Comments (10) -

Bill Beckelman
Bill Beckelman United States on 9/7/2008 7:03 AM Good point on being careful with the nested update panel by setting children as triggers to false. Thanks for sharing.
redsquare
redsquare on 9/7/2008 9:39 AM Yep, a disaster as far as footprint is concerned, 400k + for initial load and the 'ajax' paging.

Basically a great demo to showcase why you should not use ms ajax.
mosessaur
mosessaur Egypt on 9/7/2008 9:45 AM @redsquare Actually I believe that the performance of ASP.NET AJAX would improve as it is developing. So what might seem of huge load now, in future it might be improved.
I am optimistic, and still the idea isn't that bad if we can utilize it Smile .
Janko
Janko Serbia on 9/7/2008 1:36 PM One way or another, jQuery is a savior Smile Great post!
mosessaur
mosessaur Egypt on 9/7/2008 1:39 PM @Janko One way or another, I think I should try to do the same again using jQuery and check the performance Smile .
It will just take sometime.
Thank you Janko Smile
Zach
Zach United States on 9/7/2008 9:44 PM It looks great but the performance makes it unusable.  Your sample data doesn't seem very large and on idle 10Mbit connection it just slowly moves along.  Cool features at a high cost, so who's making the jQuery version for us to compare and drool over?  Great post, thanks!
redsquare
redsquare on 9/7/2008 11:20 PM @mosessaur, are you prepared to produce slow clunky apps using ms ajax in the hope that one day it will improve its footprint? I am not. Your Question should be, why did they ever produce such a bloated nightmare and can you trust anything that they produce again.
mosessaur
mosessaur Egypt on 9/8/2008 3:04 AM @Zach Thank you, and I do agree with you. But still there will be someone who might need it, or adapt it. And maybe optimized better.
For jQuery, I wish to do that, but it will require sometime to be done I guess. Anyway, maybe I got the chance soon.
Thank you again Smile
mosessaur
mosessaur Egypt on 9/8/2008 3:09 AM @redsquare ASP.NET Team is doing really great job. They are working hard. We cannot just jump at their head and tell them "You people, your tools and kits sucks!" while they really made a cool job. They will improved it, and they will enhance it. When I build my application I do care of what I should use and when. I prefer jQuery, because if east the JavaScript development and has a boost performance. But, still there people who loves to work with ASP.NET AJAX. And I like to work with both, exchanging ideas between them and play. For me it is fun, and this is community. And everybody free to pick what he wants.
Johnny
Johnny United States on 10/29/2008 8:01 PM Alan Avante you should not critique. Its the blogger's choice to do type whatever he/she wants. Indented format or double spacing. To hell with you bugger.
Comments are closed