Common Context menu
Common_ContextMenu_VBNet\SimpleTaskResults.aspx.vb
' Copyright 2010 ESRI
' 
' All rights reserved under the copyright laws of the United States
' and applicable international laws, treaties, and conventions.
' 
' You may freely redistribute and use this sample code, with or
' without modification, provided you include the original copyright
' notice and use restrictions.
' 
' See the use restrictions.
' 

Imports Microsoft.VisualBasic
Imports System
Imports System.Data
Imports System.Configuration
Imports System.Collections
Imports System.Web
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Imports System.Web.UI.HtmlControls

Public Partial Class SimpleTaskResults
  Inherits System.Web.UI.Page
  Private dynamicContextMenuItem As ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem

  Protected Sub Page_Load(ByVal sender As Object, ByVal eventArgs As System.EventArgs)
    ' Custom context menu event handlers to process event when item clicked and reset display of node is content menu dismissed.
    AddHandler ContextMenu1.ItemClicked, AddressOf ContextMenu1_ItemClicked
    AddHandler ContextMenu1.Dismissed, AddressOf ContextMenu1_Dismissed

    ' The ContextMenu control does not expose the delegates for ContextMenuItemClickedEventHandler.  If it
    ' did, you could reorder the sequence in which the delegates (event methods) are called.  In general though, 
    ' the delegates shouldn't need to be exposed publicly since the order of delegates shouldn't matter.  As a 
    ' result of this limitation, event handlers added to context menus during the creation of the TaskResults 
    ' control are added first and handlers added subsequent to creation of the TaskResults control are added 
    ' after.  When the event is triggered, the handlers are called in sequence from the first added to the last.  
    ' Thus the custom event handler referenced in the line below is called after any handlers added within the 
    ' TaskResults class itself.  So if the first handler modifies properties or components necessary for subsequent 
    ' handlers, we must override the context menu item (see ModifyFeatureContextMenu() method).
    AddHandler TaskResults1.FeatureContextMenu.ItemClicked, AddressOf FeatureContextMenu_ItemClicked
    AddHandler TaskResults1.NodeRemoved, AddressOf TaskResults1_NodeRemoved
  End Sub

  Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As EventArgs)
    If (Not IsPostBack) Then
      ContextMenu1.Items.Clear()
      Dim showAlertContextMenuItem As ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem = New ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem()
      showAlertContextMenuItem.Text = "Show Alert"
      showAlertContextMenuItem.ImageUrl = "images/alertlink.gif"
      ContextMenu1.Items.Add(showAlertContextMenuItem)
      ContextMenu1.Items.Add(TaskResults1.RemoveOnlyContextMenu.Items(0))

      ' Only occurs on initial page request (not postback).  
      ' TaskResults CreateChildControls() called during control Load event.
      ModifyFeatureContextMenu()
    End If
  End Sub

  Private Sub ContextMenu1_Dismissed(ByVal sender As Object, ByVal args As ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuDismissedEventArgs)
    Dim node As ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode = TaskResults1.Nodes.FindByNodeID(args.Context)
    If Not node Is Nothing Then
      ' Unselect node in TaskResults
      ContextMenu1.CallbackResults.Add(New ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult(Me, "javascript", String.Format("var node=document.getElementById('{0}_textCell');if(node!=null){{node.style.backgroundColor='{1}';}}", node.NodeID, System.Drawing.ColorTranslator.ToHtml(TaskResults1.BackColor))))
    End If
  End Sub

  Private Sub ContextMenu1_ItemClicked(ByVal sender As Object, ByVal contextMenuItemEventArgs As ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItemEventArgs)
    Dim treeViewPlusNode As ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode = TaskResults1.Nodes.FindByNodeID(contextMenuItemEventArgs.Context)
    Dim callbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = Nothing

    Select Case contextMenuItemEventArgs.Item.Text
      Case "Show Alert"
        callbackResult = New ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult (Nothing, Nothing, "javascript", "alert('Hello')")
        ContextMenu1.CallbackResults.Add(callbackResult)
      Case "Remove"
        treeViewPlusNode.Parent.Nodes.Remove(treeViewPlusNode)
        TaskResults1.Refresh()
        ContextMenu1.CallbackResults.CopyFrom(TaskResults1.CallbackResults)
      Case "Dynamic Show Alert"
        callbackResult = New ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult (Nothing, Nothing, "javascript", "alert('Dynamic Hello')")
        ContextMenu1.CallbackResults.Add(callbackResult)
    End Select
  End Sub

  Protected Sub Toolbar1_CommandClick(ByVal sender As Object, ByVal toolbarCommandClickEventArgs As ESRI.ArcGIS.ADF.Web.UI.WebControls.ToolbarCommandClickEventArgs)
    For Each contextMenuItem As ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem In ContextMenu1.Items
      If contextMenuItem.Text = "Dynamic Show Alert" Then
        dynamicContextMenuItem = contextMenuItem
      End If
    Next contextMenuItem

    ' name of the Command in the Toolbar
    Select Case toolbarCommandClickEventArgs.CommandName
      Case ("AddNode")

        If Not dynamicContextMenuItem Is Nothing Then
          ContextMenu1.Items.Remove(dynamicContextMenuItem)
        End If

        Dim headingTaskResultNode As ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResultNode = New ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResultNode("Heading")

        Dim detailTreeViewPlusNode As ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode = New ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode("Detail")
        TaskResults1.SetupContextMenu(ContextMenu1, detailTreeViewPlusNode)
        headingTaskResultNode.Nodes.Add(detailTreeViewPlusNode)
        detailTreeViewPlusNode.EnsureVisible()

        ' Only necessary because dynamic context menu items may have been added\removed
        'ContextMenu1.Refresh();
        Toolbar1.CallbackResults.CopyFrom(ContextMenu1.CallbackResults)

        TaskResults1.DisplayResults(Nothing, Nothing, Nothing, headingTaskResultNode)
        Toolbar1.CallbackResults.CopyFrom(TaskResults1.CallbackResults)

      Case ("AddNodeWithDynamicItem")

        If dynamicContextMenuItem Is Nothing Then
          dynamicContextMenuItem = New ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem()
          dynamicContextMenuItem.Text = "Dynamic Show Alert"
          dynamicContextMenuItem.ImageUrl = "images/wrench.gif"
          ContextMenu1.Items.Add(dynamicContextMenuItem)
                    'ContextMenu1.Refresh()
        End If

        Dim dymamicHeadingTaskResultNode As ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResultNode = New ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResultNode("Heading")

        Dim dynamicDetailTreeViewPlusNode As ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode = New ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode("Dynamic Node Detail")
        TaskResults1.SetupContextMenu(ContextMenu1, dynamicDetailTreeViewPlusNode)
        dymamicHeadingTaskResultNode.Nodes.Add(dynamicDetailTreeViewPlusNode)
        dynamicDetailTreeViewPlusNode.EnsureVisible()

        TaskResults1.DisplayResults(Nothing, Nothing, Nothing, dymamicHeadingTaskResultNode)
        Toolbar1.CallbackResults.CopyFrom(TaskResults1.CallbackResults)

    End Select
  End Sub

  ' Fired when a node is removed from the TaskResults control
  Private Sub TaskResults1_NodeRemoved(ByVal sender As Object, ByVal treeViewPlusNodeRemovedEventArgs As ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNodeRemovedEventArgs)
    ' Store the removed node and its parent in session
    Session("RemovedNode") = treeViewPlusNodeRemovedEventArgs.Node
    Session("RemovedNodeParent") = treeViewPlusNodeRemovedEventArgs.Parent
  End Sub

  ' Check context menu items on TaskResults FeatureContextMenu for existing custom item 
  Protected Function contextMenuPredicateHandler(ByVal target As ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem) As Boolean
    If target.Text = "Remove Node" Then
      Return True
    Else
      Return False
    End If
  End Function

  ' Adds a context menu item for removing the current node from the TaskResults control
  ' Called during PreRender
  Private Sub ModifyFeatureContextMenu()
    Dim contextMenuPredicate As System.Predicate(Of ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem) = New System.Predicate(Of ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem) (AddressOf contextMenuPredicateHandler)
    If (Not TaskResults1.FeatureContextMenu.Items.Exists(contextMenuPredicate)) Then
      Dim deleteNodeContextMenuItem As ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem = New ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem()
      deleteNodeContextMenuItem.Text = "Remove Node"
      deleteNodeContextMenuItem.ImageUrl = "images/delete.gif"

      TaskResults1.FeatureContextMenu.Items.Add(deleteNodeContextMenuItem)
    End If
  End Sub

  ' Fires when a context menu item is clicked
  Private Sub FeatureContextMenu_ItemClicked(ByVal sender As Object, ByVal contextMenuItemEventArgs As ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItemEventArgs)
    ' Get the clicked node
    Dim featureNode As ESRI.ArcGIS.ADF.Web.UI.WebControls.FeatureNode = CType(TaskResults1.Nodes.FindByNodeID(contextMenuItemEventArgs.Context), ESRI.ArcGIS.ADF.Web.UI.WebControls.FeatureNode)
    Dim parentNode As ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode = Nothing
    Dim contextMenu As ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenu = Nothing
    Dim taskResults As ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults = Nothing

    ' Check which context menu item was clicked
    Select Case contextMenuItemEventArgs.Item.Text
      ' Preconfigured with the TaskResults context menus, thus the node has already been removed.  
      ' The NodeRemoved event has already fired.
      Case "Remove"
        contextMenu = CType(sender, ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenu)
        featureNode = CType(Session("RemovedNode"), ESRI.ArcGIS.ADF.Web.UI.WebControls.FeatureNode)

        If Not featureNode Is Nothing Then
          parentNode = CType(Session("RemovedNodeParent"), ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode)
          parentNode.Refresh()
          taskResults = CType(contextMenuItemEventArgs.Control, ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults)
          contextMenu.CallbackResults.CopyFrom(taskResults.CallbackResults)
        End If

      ' Custom context menu item, thus explicit removal is required.
      ' The NodeRemoved event when Remove method is called on feature node.
      Case "Remove Node"

        If Not featureNode Is Nothing Then
          If Not Map1 Is Nothing Then
            contextMenu = CType(sender, ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenu)

            ' Delete data row associated with feature node
            Dim dataRow As System.Data.DataRow = featureNode.DataRow
            dataRow.Delete()

            ' Refresh map resource that displays feature associated with feature node
            If TypeOf dataRow.Table Is ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsLayer AndAlso Not dataRow.Table.DataSet Is Nothing AndAlso ((Not String.IsNullOrEmpty(dataRow.Table.DataSet.DataSetName))) Then
              Map1.RefreshResource(dataRow.Table.DataSet.DataSetName)

              ' Context menu is responsible from generating callback response, thus
              ' copy callback results to context menu callback results collection.
              contextMenu.CallbackResults.CopyFrom(Map1.CallbackResults)
            End If

            ' Refresh node within TaskResults 
            parentNode = CType(featureNode.Parent, ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode)

            ' Delete the feature node from the TaskResults display
            featureNode.Remove()

            parentNode.Refresh()

            taskResults = CType(contextMenuItemEventArgs.Control, ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults)

            ' Context menu is responsible from generating callback response, thus
            ' copy callback results to context menu callback results collection.
            contextMenu.CallbackResults.CopyFrom(taskResults.CallbackResults)
          End If
        End If
    End Select
  End Sub
End Class