Adding context menus to a Web ADF application

In this post, Rex Hansen provides a sneak peek at a forthcoming EDN article on adding context menus to your .Net Web ADF applications.

The ContextMenu control allows users to interact with your Web ADF application at runtime, usually by right-clicking a component. A ContextMenu can contain one or more context menu items. Each item is associated with an action to execute client or server-side code. In addition, each context menu item may be displayed with an icon andor text. Both the Toc and TaskResults controls include preconfigured ContextMenus to interact with their node content. 

The ContextMenu control is not included with the out-of-the-box Web ADF controls integrated with Visual Studio. So, to use the control you can either add a declarative reference in your page or add the ContextMenu control to the Visual Studio toolbox then drag-and-drop it on the page (see Step 1 in Using the ContextMenu control section below). In addition, you must configure context menu items programmatically; no design-time configuration is provided. 

Using the ContextMenu control

  1. Add the ContextMenu control to the Visual Studio toolbox

    Since the ContextMenu control is not added to the Visual Studio toolbox during the Web ADF installation, you need to manually add it. If you have already added the ContextMenu control, skip to the next step.

    1. In Visual Studio, expand the ArcGIS Web Controls tab in the toolbox. Right-click on the tab and select “Choose Items…”.
    2. Navigate to the ContextMenu control in the namespace ESRI.ArcGIS.ADF.UI.WebControls and check the box next to the listing. Click OK. The ContextMenu control should now be available in the toolbox.

      Page with Toc control

  2. Add supporting controls to the page

    Add a MapResourceManager and Map to the page, then add a valid resource item to the MapResourceManager. In this example, we’ll construct a ContextMenu for use on a Map control. Keep in mind that a ContextMenu can be associated with any element in the page, thus the patterns presented here will apply in other situations. 

  3. Add the ContextMenu control to the page

    Drag a ContextMenu control on the page. Note that the location of the ContextMenu control at design-time does not determine the location of the context menu at runtime. Your page should resemble the following:

    Page with Toc control

  4. Set properties for the ContextMenu control

    In design mode, click on the ContextMenu control to select it. Now examine the control’s properties in the Properties window. You don’t have to manually change any of the properties, but it’s recommended that you set the BackColor property to a solid color, for example, white or gray. By default the BackColor property is not set, so the context menu appears transparent at runtime.

  5. Add context menu items

    Adding items and configuring the behavior of a ContextMenu requires writing some code. You can create new context menu items by using the ContextMenuItem class and then adding them to the ContextMenu control. Properties of a ContextMenuItem include the url to an image, the menu item text, and a string representing some custom JavaScript code to execute when the item is clicked. An appropriate time to add new context menu items during the page lifecycle is during the initial page load event. Add the following code to the code behind for your page:

    [C#]

    protected void Page_Load(object sender, EventArgs e)
    {
      if (!IsPostBack)
      {
        ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem contextMenuItem =
          new ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem();
    
        contextMenuItem.Text = "Zoom In";
    
        ContextMenu1.Items.Add(contextMenuItem);
      }
    }
    
  6. Add event to show context menu at runtime 

    In order to display the context menu at the appropriate time, you need to add a browser event to the appropriate control, element, or item in the page. In this case, we want the ContextMenu to be displayed during a right-click on a map. At runtime, the Map control generates a div for display of map data in a browser. A set of attributes events can be configured on the div. One attribute is “oncontextmenu” which enables the browser to listen for right-click events on an element. When this event is triggered, JavaScript code displays the the ContextMenu control and its items. The Web ADF provides a set of JavaScript functions to show and hide context menus. In this case, when the oncontextmenu event is triggered on the map the esriShowContextMenu() JavaScript function will be called and our ContextMenu will be displayed. As in the previous step, an appropriate time to add new attribute information to controls and elements is during the initial page load event. Add the following code (blue) to the existing code added in the previous step (gray):

    [C#]

    protected void Page_Load(object sender, EventArgs e)
    {
      if (!IsPostBack)
      {
        ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem contextMenuItem =
          new ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem();
    
        contextMenuItem.Text = "Zoom In";
    
        ContextMenu1.Items.Add(contextMenuItem);
    
        string showContextMenu = string.Format("esriShowContextMenu(event,'{0}','{1}','{2}');return false;", ContextMenu1.ClientID, Map1.UniqueID, "");
    
        Map1.Attributes.Add("oncontextmenu", showContextMenu);    
      }
    }
    
  7. Handle click event on context menu item

    Once the ContextMenu is displayed at runtime, a user can click on a context menu item to initiate an action. To work with the click event on the server, handle the ItemClicked event on the ContextMenu. When the menu item is clicked, a callback request is sent to the page which contains the context menu. The context menu item can be identified by its text and made available via the ContextMenuItemEventArgs passed to the ItemClicked event. The ContextMenu control is explicitly designed to work with the ASP.NET callback architecture. Implementation code on the server can now interact with server-side content based on the context menu item clicked. Note, the ContextMenu control generates the callback response designed to be processed by the Web ADF JavaScript. As a result, changes to other controls in the page must be packaged as CallbackResults and added to the ContextMenu.CallbackResults property (a collection of CallbackResult objects). More information on Web ADF implementation of the ASP.NET callback framework is available in the topic Working with AJAX capabilities of the Web ADF.

    1. To handle the ItemClicked event on the ContextMenu in the page, open the ContextMenu property page and view the events (click the lightning bolt button).

      Page with Toc control

    2. Double-click on the ItemClicked event in the dialog. The code-behind page will display with the implementation method created for you.
    3. Add the following code to the event handler method. In this case, the Map.Zoom() convenience method will cause the map to zoom in, thus changing the map extent. Since the Map has changed, but the ContextMenu is generating the callback response, the callback results from the Map control need to be copied to the ContextMenu’s callback results collection.

      [C#]

      protected void ContextMenu1_ItemClicked(object sender, ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItemEventArgs contextMenuItemEventArgs)
      {
        switch (contextMenuItemEventArgs.Item.Text)
        {
          case "Zoom In":
            {
              Map1.Zoom(2);
              ContextMenu1.CallbackResults.CopyFrom(Map1.CallbackResults);
              break;
            }
        }
      }
      					
  8. Using the ContextMenu at runtime

    When the Web application starts, the ContextMenu is not visible. Right-click on the control which will show the ContextMenu (In this example it’s the Map control). The ContextMenu will be displayed along with it’s context menu items. In this case, click on the item “Zoom In” to zoom in on the map.  

    Page with Toc control

This entry was posted in Services and tagged , , . Bookmark the permalink.

Leave a Reply

5 Comments

  1. drxp2006 says:

    Sorry text format is bad, from comments it can’t be fixed.

    Could you fix it instead of me.

  2. sterlingdq says:

    drxp- I assume you mean the code above by “From Turkey – Istanbul”. I added some formatting tags and it looks better on our side. Let me know if there’s still problems.

  3. drxp2006 says:

    Thanks a lot. There is no problem now. Also i was the “From Turkey – Istanbul” user. drxp. And that’s the my first comment. :)

  4. iamlaksh3 says:

    Hello, am using AGS 9.2 and .NET. I’ve added context menu to TOC and added items. Whenever user right clicks TOC, the context menu pop up with “Set as Active Layer” and thats sets as active layer.

    Here context menu working fine for first time and second time am pNode is null. Hence I couldnot do any thing.

    Can anyone help on this?. Very urgent

    Contextmenu_ItemClicked
    {
    ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode pNode = Toc1.Nodes.FindByNodeID(args.Context);
    }

    protected void ContextMenu1_ItemClicked(object sender, ContextMenuItemEventArgs args)
    {
    try
    {

    ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode pNode = Toc1.Nodes.FindByNodeID(args.Context);

    if (pNode != null)
    {
    ESRI.ArcGIS.ADF.ArcGISServer.MapLayerInfo pMapLayerInfo = null;
    EnvelopeN pEnvolope = null;
    MapResourceLocal mapResource = null;

    // First, check the map resourceitems

    foreach (MapResourceItem mri in MapResourceManager1.ResourceItems)
    {
    if (mri != null)
    {
    mapResource = mri.Resource as MapResourceLocal;
    if (mapResource != null)
    {
    MapResourceLocal localRes = mapResource as MapResourceLocal;
    foreach (ESRI.ArcGIS.ADF.ArcGISServer.MapLayerInfo pMapLyrInfo in mapResource.MapServerInfo.MapLayerInfos)
    {
    if (pNode.Text == pMapLyrInfo.Name)
    {
    pMapLayerInfo = pMapLyrInfo;
    break;
    }
    }
    }
    }
    }

    switch (args.Item.Text)
    {

    case “Select as Active Layer”:
    //pNode.TextCellStyleAttributes.Add(“color”, System.Drawing.ColorTranslator.ToHtml(System.Drawing.Color.Blue));

    ContextMenu1.CallbackResults.Add(RefreshControlHTML(Toc1));
    Toc1.Refresh();
    Toc1.ExpandDepth = 1;
    SetupTOCContextMenu();
    ContextMenu1.CallbackResults.Add(RefreshControlHTML(Toc1));
    mapResource.RefreshServerObjects();
    break;
    default:
    //dostuff;
    break;
    }

    } //pNode

    }

    catch (Exception ex)
    {
    callErrorPage(ex.Message, null);
    }
    finally
    {
    }

    }
    protected void ContextMenu1_Dismissed(object sender, ContextMenuDismissedEventArgs args)
    {
    try
    {

    ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode pNode = Toc1.Nodes.FindByNodeID(args.Context);

    if (pNode != null)
    {

    ContextMenu1.CallbackResults.Add(new ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult(this, “javascript”, String.Format(“var node=document.getElementById(‘{0}’);if(node!=null){{node.style.backgroundColor=’{1}’;}}”, pNode.NodeID + “_textCell”, System.Drawing.ColorTranslator.ToHtml(Toc1.BackColor))));

    }

    }

    catch (Exception ex)
    {

    callErrorPage(ex.Message, null);

    }

    }

    private ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult RefreshControlHTML(Control control)
    {

    try
    {
    System.IO.StringWriter strWriter = new System.IO.StringWriter();
    HtmlTextWriter htmlWriter = new HtmlTextWriter(strWriter);
    control.RenderControl(htmlWriter);
    string htmlContent = strWriter.ToString();
    strWriter.Close();
    return new CallbackResult(control, “content”, htmlContent);
    }

    catch (Exception ex)
    {
    callErrorPage(ex.Message, null);
    return null;
    }
    finally
    {
    }

    }

  5. ekenn001 says:

    Does anyone know how to add a context menu using the Web ADF in JAVA??????????