Home / Community & Support / Knowledge Base / RadControls for ASP.NET and ASP.NET AJAX / Grid / AJAX-enabled RadMenu as context menu in RadGrid

AJAX-enabled RadMenu as context menu in RadGrid

Article Info

Rating: 4

Article information

Article relates to

RadGrid, RadMenu, RadAjax
or
Telerik.Web.UI 2007.12.18+

Created by

Stephen, Telerik

Last modified

March 12, 2008

Last modified by

Stephen, Telerik

HOW-TO
Configure Ajax-enabled RadMenu as context menu in RadGrid

DESCRIPTION
In numerous cases you may want to display a context menu when right-clicking an arbitrary row in RadGrid. Through a command from that context menu you may want to change the state for the grid row (for example edit/delete/add record). Furthermore, you may prefer the operation with asynchronous request instead of postback. 

  

SOLUTION

The solution is illustrated in this online demo, using the latest version of the controls.


The seamless integration between RadContextMenu, RadAjax and RadGrid makes this task very easy to be accomplished. Our grid control exposes OnRowContextMenu client event which can be handled to select the right-clicked record in the grid to mark it as active for the current action. In order to determine the index of the clicked row on the server, use a hidden field on the page to store its value client side and then operate with it on form submit (in the ItemClick event handler of RadMenu). Inside the handler perform the corresponding task chosen by the user to modify the item state.

To associate the context menu with the grid instance, attach the OnRowContextMenu client event of RadGrid, get reference to the context menu object client-side and invoke its show method (passing the browser's event argument as parameter).

Finally, configure the ajax manager settings in order to refresh the grid and the menu in a codeless manner.

ASPX/ASCX

C#

        <asp:ScriptManager ID="ScriptManager1" runat="server" /> 
          <telerik:RadScriptBlock runat="server" ID="RadScriptBlock1">  
 
            <script type="text/javascript">  
            function RowContextMenu(sender, eventArgs)  
            {  
                var menu = $find("<%=RadMenu1.ClientID %>");  
                var evt = eventArgs.get_domEvent();  
                  
                var index = eventArgs.get_itemIndexHierarchical();  
                document.getElementById("radGridClickedRowIndex").value = index;  
                  
                sender.get_masterTableView().selectItem(sender.get_masterTableView().get_dataItems()[index].get_element(), true);  
                  
                menu.show(evt);  
                  
                evt.cancelBubble = true;  
                evt.returnValue = false;  
 
                if (evt.stopPropagation)  
                {  
                   evt.stopPropagation();  
                   evt.preventDefault();  
                }  
            }  
            </script> 
 
        </telerik:RadScriptBlock> 
        <telerik:RadAjaxManager ID="RadAjaxManager1" runat="server">  
            <AjaxSettings> 
                <telerik:AjaxSetting AjaxControlID="RadGrid1">  
                    <UpdatedControls> 
                        <telerik:AjaxUpdatedControl ControlID="RadGrid1" LoadingPanelID="AjaxLoadingPanel1" /> 
                        <telerik:AjaxUpdatedControl ControlID="RadMenu1" /> 
                    </UpdatedControls> 
                </telerik:AjaxSetting> 
                <telerik:AjaxSetting AjaxControlID="RadMenu1">  
                    <UpdatedControls> 
                        <telerik:AjaxUpdatedControl ControlID="RadGrid1" LoadingPanelID="AjaxLoadingPanel1" /> 
                        <telerik:AjaxUpdatedControl ControlID="RadMenu1" /> 
                    </UpdatedControls> 
                </telerik:AjaxSetting> 
            </AjaxSettings> 
        </telerik:RadAjaxManager> 
        <telerik:RadAjaxLoadingPanel ID="AjaxLoadingPanel1" runat="server" Height="75px" 
            Width="75px" Transparency="25">  
            <img alt="Loading..." src='<%= RadAjaxLoadingPanel.GetWebResourceUrl(Page, "Telerik.Web.UI.Skins.Default.Ajax.loading.gif") %>' 
                style="border: 0;" /> 
        </telerik:RadAjaxLoadingPanel> 
        <input type="hidden" id="radGridClickedRowIndex" name="radGridClickedRowIndex" /> 
        <p> 
            Right-click the grid to open context menu.</p> 
        <div style="margin-right: 20px;">  
            <telerik:RadGrid ID="RadGrid1" runat="server" Width="100%" GridLines="None" BorderWidth="0" 
                DataSourceID="SessionDataSource1" AllowAutomaticDeletes="true" AllowAutomaticInserts="true" 
                AllowAutomaticUpdates="true" Skin="Vista" OnPreRender="RadGrid1_PreRender">  
                <MasterTableView AllowSorting="False" PageSize="10" AllowPaging="True" Width="100%" 
                    DataKeyNames="ProductID" DataSourceID="SessionDataSource1" EditMode="InPlace">  
                    <Columns> 
                        <telerik:GridEditCommandColumn UniqueName="EditCommandColumn" Visible="false" /> 
                    </Columns> 
                </MasterTableView> 
                <ClientSettings> 
                    <ClientEvents OnRowContextMenu="RowContextMenu"></ClientEvents> 
                    <Selecting AllowRowSelect="true" /> 
                </ClientSettings> 
                <PagerStyle Mode="NextPrevAndNumeric" /> 
            </telerik:RadGrid> 
        </div> 
        <br /> 
        <sds:SessionDataSource ID="SessionDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>" 
            SelectCommand="SELECT ProductID, ProductName,QuantityPerUnit,UnitPrice, UnitsInStock FROM [Products]" 
            DeleteCommand="DELETE FROM [Products] WHERE [ProductID] = ?" InsertCommand="INSERT INTO Products(ProductName, SupplierID, CategoryID, QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" 
            UpdateCommand="UPDATE [Products] SET [ProductName] = ?,[QuantityPerUnit] = ?, [UnitPrice] = ?, [UnitsInStock] = ? WHERE [ProductID] = ? AND [ProductName] = ? AND [QuantityPerUnit] = ? AND [UnitPrice] = ? AND [UnitsInStock] = ?" 
            PrimaryKeyFields="ProductID" OldValuesParameterFormatString="original_{0}" 
            ConflictDetection="CompareAllValues">  
            <DeleteParameters> 
                <asp:Parameter Name="original_ProductID" Type="Int32" /> 
            </DeleteParameters> 
            <UpdateParameters> 
                <asp:Parameter Name="ProductName" Type="String" /> 
                <asp:Parameter Name="QuantityPerUnit" Type="String" /> 
                <asp:Parameter Name="UnitPrice" Type="Decimal" /> 
                <asp:Parameter Name="UnitsInStock" Type="Int16" /> 
                <asp:Parameter Name="original_ProductID" Type="Int32" /> 
                <asp:Parameter Name="original_ProductName" Type="String" /> 
                <asp:Parameter Name="original_QuantityPerUnit" Type="String" /> 
                <asp:Parameter Name="original_UnitPrice" Type="Decimal" /> 
                <asp:Parameter Name="original_UnitsInStock" Type="Int16" /> 
            </UpdateParameters> 
            <InsertParameters> 
                <asp:Parameter Name="ProductName" Type="String" /> 
                <asp:Parameter Name="SupplierID" Type="Int32" /> 
                <asp:Parameter Name="CategoryID" Type="Int32" /> 
                <asp:Parameter Name="QuantityPerUnit" Type="String" /> 
                <asp:Parameter Name="UnitPrice" Type="Decimal" /> 
                <asp:Parameter Name="UnitsInStock" Type="Int16" /> 
                <asp:Parameter Name="UnitsOnOrder" Type="Int16" /> 
                <asp:Parameter Name="ReorderLevel" Type="Int16" /> 
                <asp:Parameter Name="Discontinued" Type="Boolean" /> 
            </InsertParameters> 
        </sds:SessionDataSource> 
        <telerik:RadContextMenu ID="RadMenu1" runat="server" Skin="Vista" OnItemClick="RadMenu1_ItemClick">  
            <Items> 
                <telerik:RadMenuItem Text="Add" /> 
                <telerik:RadMenuItem Text="Edit" /> 
                <telerik:RadMenuItem Text="Delete" /> 
            </Items> 
        </telerik:RadContextMenu> 

 

 

 

        protected void RadMenu1_ItemClick(object sender, RadMenuEventArgs e)  
        {  
            int radGridClickedRowIndex;  
 
            radGridClickedRowIndex = Convert.ToInt32(Request.Form["radGridClickedRowIndex"]);  
 
            switch (e.Item.Text)  
            {  
                case "Edit":  
                    RadGrid1.Items[radGridClickedRowIndex].Edit = true;  
                    RadGrid1.Rebind();  
                    break;  
                case "Add":  
                    RadGrid1.MasterTableView.IsItemInserted = true;  
                    RadGrid1.Rebind();  
                    break;  
                case "Delete":  
                    RadGrid1.MasterTableView.PerformDelete(RadGrid1.Items[radGridClickedRowIndex]);  
                    break;  
            }  
        }  
        protected void RadGrid1_PreRender(object sender, EventArgs e)  
        {  
            if (RadGrid1.EditIndexes.Count > 0 || RadGrid1.MasterTableView.IsItemInserted)  
            {  
                GridColumn col1 = RadGrid1.MasterTableView.GetColumn("EditCommandColumn"as GridColumn;  
                col1.Visible = true;  
            }  
            else 
            {  
                GridColumn col2 = RadGrid1.MasterTableView.GetColumn("EditCommandColumn"as GridColumn;  
                col2.Visible = false;  
            }      
        } 

VB.NET

    Protected Sub RadMenu1_ItemClick(ByVal sender As ObjectByVal e As RadMenuEventArgs) Handles RadMenu1.ItemClick  
        Dim radGridClickedRowIndex As Integer 
 
        radGridClickedRowIndex = Convert.ToInt32(Request.Form("radGridClickedRowIndex"))  
        Select Case e.Item.Text  
            Case "Edit" 
                RadGrid1.Items(radGridClickedRowIndex).Edit = True 
                RadGrid1.Rebind()  
            Case "Add" 
                RadGrid1.MasterTableView.IsItemInserted = True 
                RadGrid1.Rebind()  
            Case "Delete" 
                RadGrid1.MasterTableView.PerformDelete(RadGrid1.Items(radGridClickedRowIndex))  
        End Select 
    End Sub 'RadMenu1_ItemClick  
 
 
    Protected Sub RadGrid1_PreRender(ByVal sender As ObjectByVal e As EventArgs) Handles RadGrid1.PreRender  
        If RadGrid1.EditIndexes.Count > 0 Or RadGrid1.MasterTableView.IsItemInserted Then 
            Dim col1 As GridColumn = CType(RadGrid1.MasterTableView.GetColumn("EditCommandColumn"), GridColumn)  
            col1.Visible = True 
        Else 
            Dim col2 As GridColumn = CType(RadGrid1.MasterTableView.GetColumn("EditCommandColumn"), GridColumn)  
            col2.Visible = False 
        End If 
    End Sub 'RadGrid1_PreRender 



SOLUTION
The seamless integration between RadMenu, RadAjax and RadGrid makes this task very easy to be accomplished. Our grid control exposes OnRowContextMenu client event which can be handled to obtain reference to the client object of RadMenu and call its Show method (passing event argument as parameter). In order to determine the index of the clicked row on the server, you can use a hidden field on the page to store its value client side and then operate with it on form submit (inside the ItemClick event handler of RadMenu). Inside the handler perform the corresponding task chosen by the user to modify the item state.
Finally, configure the ajax manager settings in order to refresh the grid and the menu in a codeless manner.

ASPX/ASCX

        <script type="text/javascript">  
            function RowContextMenu(index, e)  
            {  
                document.getElementById("RadGridClickedRowIndex").value = index;  
                var menu = <%= RadMenu1.ClientID %>;  
                menu.Show(e);  
                  
                e.cancelBubble = true;  
                e.returnValue = false;  
 
                if (e.stopPropagation)  
                {  
                   e.stopPropagation();  
                   e.preventDefault();  
                }  
                this.SelectRow(this.Rows[index].Control, true);  
            }  
        </script> 
 
        <radA:RadAjaxManager ID="RadAjaxManager1" runat="server" EnableAJAX="true">  
            <AjaxSettings> 
                <radA:AjaxSetting AjaxControlID="RadGrid1">  
                    <UpdatedControls> 
                        <radA:AjaxUpdatedControl ControlID="RadGrid1" LoadingPanelID="AjaxLoadingPanel1" /> 
                    </UpdatedControls> 
                </radA:AjaxSetting> 
                <radA:AjaxSetting AjaxControlID="RadMenu1">  
                    <UpdatedControls> 
                        <radA:AjaxUpdatedControl ControlID="RadGrid1" LoadingPanelID="AjaxLoadingPanel1" /> 
                        <radA:AjaxUpdatedControl ControlID="RadMenu1" /> 
                    </UpdatedControls> 
                </radA:AjaxSetting> 
            </AjaxSettings> 
        </radA:RadAjaxManager> 
        <radA:AjaxLoadingPanel ID="AjaxLoadingPanel1" runat="server" Height="75px" Width="75px" 
            Transparency="25">  
            <asp:Image ID="Image1" runat="server" AlternateText="Loading..." ImageUrl="~/RadControls/Ajax/Skins/Default/Loading.gif" /> 
        </radA:AjaxLoadingPanel> 
        <input type="hidden" id="RadGridClickedRowIndex" name="RadGridClickedRowIndex" /> 
        <p> 
            Right-click the grid to open context menu.</p> 
        <div style="margin-right: 20px;">  
            <radg:RadGrid ID="RadGrid1" runat="server" Width="100%" GridLines="None" BorderWidth="0" 
                DataSourceID="SessionDataSource1" AllowAutomaticDeletes="true" AllowAutomaticInserts="true" 
                AllowAutomaticUpdates="true" Skin="Glassy" OnPreRender="RadGrid1_PreRender">  
                <MasterTableView AllowSorting="False" PageSize="10" AllowPaging="True" Width="100%" 
                    DataKeyNames="ProductID" DataSourceID="SessionDataSource1" EditMode="InPlace">  
                    <Columns> 
                        <radg:GridEditCommandColumn UniqueName="EditCommandColumn" Visible="false" /> 
                    </Columns> 
                </MasterTableView> 
                <ClientSettings> 
                    <ClientEvents OnRowContextMenu="RowContextMenu"></ClientEvents> 
                    <Selecting AllowRowSelect="true" /> 
                </ClientSettings> 
                <PagerStyle Mode="NextPrevAndNumeric" /> 
            </radg:RadGrid> 
        </div> 
        <br /> 
        <sds:SessionDataSource ID="SessionDataSource1" runat="server" DataFile="~/Grid/Data/Access/NWind.mdb" 
            SelectCommand="SELECT ProductID, ProductName,QuantityPerUnit,UnitPrice, UnitsInStock  FROM [Products]" 
            DeleteCommand="DELETE FROM [Products] WHERE [ProductID] = ?" InsertCommand="INSERT INTO Products(ProductName, SupplierID, CategoryID, QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)" 
            UpdateCommand="UPDATE [Products] SET [ProductName] = ?,[QuantityPerUnit] = ?, [UnitPrice] = ?, [UnitsInStock] = ? WHERE [ProductID] = ? AND [ProductName] = ? AND [QuantityPerUnit] = ? AND [UnitPrice] = ? AND [UnitsInStock] = ?" 
            AutoIncrementFields="ProductID" OldValuesParameterFormatString="original_{0}" 
            ConflictDetection="CompareAllValues">  
            <DeleteParameters> 
                <asp:Parameter Name="original_ProductID" Type="Int32" /> 
            </DeleteParameters> 
            <UpdateParameters> 
                <asp:Parameter Name="ProductName" Type="String" /> 
                <asp:Parameter Name="QuantityPerUnit" Type="String" /> 
                <asp:Parameter Name="UnitPrice" Type="Decimal" /> 
                <asp:Parameter Name="UnitsInStock" Type="Int16" /> 
                <asp:Parameter Name="original_ProductID" Type="Int32" /> 
                <asp:Parameter Name="original_ProductName" Type="String" /> 
                <asp:Parameter Name="original_QuantityPerUnit" Type="String" /> 
                <asp:Parameter Name="original_UnitPrice" Type="Decimal" /> 
                <asp:Parameter Name="original_UnitsInStock" Type="Int16" /> 
            </UpdateParameters> 
            <InsertParameters> 
                <asp:Parameter Name="ProductName" Type="String" /> 
                <asp:Parameter Name="SupplierID" Type="Int32" /> 
                <asp:Parameter Name="CategoryID" Type="Int32" /> 
                <asp:Parameter Name="QuantityPerUnit" Type="String" /> 
                <asp:Parameter Name="UnitPrice" Type="Decimal" /> 
                <asp:Parameter Name="UnitsInStock" Type="Int16" /> 
                <asp:Parameter Name="UnitsOnOrder" Type="Int16" /> 
                <asp:Parameter Name="ReorderLevel" Type="Int16" /> 
                <asp:Parameter Name="Discontinued" Type="Boolean" /> 
            </InsertParameters> 
        </sds:SessionDataSource> 
        <radm:RadMenu ID="RadMenu1" IsContext="True" runat="server" Skin="Outlook" OnItemClick="RadMenu1_ItemClick" 
            ContextMenuElementID="none">  
            <Items> 
                <radm:RadMenuItem Text="Add" /> 
                <radm:RadMenuItem Text="Edit" /> 
                <radm:RadMenuItem Text="Delete" /> 
            </Items> 
        </radm:RadMenu> 

C#

        protected void RadMenu1_ItemClick(object sender, RadMenuEventArgs e)  
        {  
            int RadGridClickedRowIndex;  
      
            RadGridClickedRowIndex = Convert.ToInt32(Request.Form["RadGridClickedRowIndex"]);  
            switch(e.Item.Text)  
            {  
                case "Edit":  
                    RadGrid1.Items[RadGridClickedRowIndex].Edit = true;  
                    RadGrid1.Rebind();  
                    break;  
                case "Add":  
                    RadGrid1.MasterTableView.IsItemInserted = true;  
                    RadGrid1.Rebind();  
                    break;  
                case "Delete":  
                    RadGrid1.MasterTableView.PerformDelete(RadGrid1.Items[RadGridClickedRowIndex] as GridEditableItem);  
                    break;  
            }  
        }  
 
        protected void RadGrid1_PreRender(object sender, EventArgs e)  
        {  
            if (RadGrid1.EditIndexes.Count > 0 || RadGrid1.MasterTableView.IsItemInserted)  
            {  
                (RadGrid1.MasterTableView.GetColumn("EditCommandColumn"as GridColumn).Visible = true;  
            }  
            else 
            {  
                (RadGrid1.MasterTableView.GetColumn("EditCommandColumn"as GridColumn).Visible = false;  
            }  
        } 

VB.NET

        Protected Sub RadMenu1_ItemClick(ByVal sender As ObjectByVal e As RadMenuEventArgs) 
            Dim RadGridClickedRowIndex As Integer 
            RadGridClickedRowIndex = Convert.ToInt32(Request.Form("RadGridClickedRowIndex"))  
            Select Case e.Item.Text  
                Case "Edit" 
                    RadGrid1.Items(RadGridClickedRowIndex).Edit = True 
                    RadGrid1.Rebind()  
                Case "Add" 
                    RadGrid1.MasterTableView.IsItemInserted = True 
                    RadGrid1.Rebind()  
                Case "Delete" 
                    RadGrid1.MasterTableView.PerformDelete(CType(RadGrid1.Items(RadGridClickedRowIndex), GridEditableItem))  
            End Select 
        End Sub 
 
        Protected Sub RadGrid1_PreRender(ByVal sender As ObjectByVal e As EventArgs) Handles RadGrid1.PreRender  
            If RadGrid1.EditIndexes.Count > 0 OrElse RadGrid1.MasterTableView.IsItemInserted Then 
                CType(RadGrid1.MasterTableView.GetColumn("EditCommandColumn"), GridColumn).Visible = True 
            Else 
                CType(RadGrid1.MasterTableView.GetColumn("EditCommandColumn"), GridColumn).Visible = False 
            End If 
        End Sub 

The purpose of the example is to demonstrate integration between RadGrid, RadAjax and RadMenu in a Windows Explorer-like web application.

Variations for context menu (in hierarchical grid or different menus per level) are presented here:
Context menu in hierarchy

Note: The SessionDataSource in this demo is a modified version of an SqlDataSource control which stores the modified data in the Session. You can attain the same functionality with standard data source controls (AccessDataSource/SqlDataSource/ObjectDataSource) by replacing the SessionDataSource.dll and configuring them appropriately (with UpdateInsert/Delete parameters). See this online demo for more info

Demo projects are enclosed at the end of this thread for further reference.

Comments

  • SilverRonin , Jan 24, 2008

    I am trying to use this example in one of my projects and i seem to have found a problem that I could really use some help with. If you run the demo project and use the delete function. Instead of deleting one row, two rows are deleted. Has anyone resolved this issue already? Thanks in advance, Dewayne Mikkelson Wachovia

  • Telerik Admin , Jan 29, 2008

    Indeed the issue is due to duplicate handling of the ItemClicked event of the menu (both in the aspx and from the code-behind). The example have been updated and everything should be fine now - thank you for pointing out this glitch.

If you'd like to comment on this KB article, please, send us a Support Ticket.
Thank you!

Please Sign In to rate this article.