Last year, Matt posted a cool post about How To: Use the HoverMenuExtender for GridView RowCommands. 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 Master\Detail GridView with CollapsiblePanelExtender 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 How To: Use the HoverMenuExtender for GridView RowCommands 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.
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.
