Common Task results
Common_TaskResults_VBNet\TaskResultsWebSite\App_Code\SelectTool.vb
' Copyright 2011 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.
' 

' Selects the features from the active layer that lie within the user-drawn rectangle.  Replaces the contents of
' the Selected Set task result node with these features, or creates a new Selected Set node if necessary.

Imports Microsoft.VisualBasic
Imports System
Public Class SelectTool
  Implements ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools.IMapServerToolAction
  #Region "IMapServerToolAction Members - ServerAction"

  Private Sub ServerAction(ByVal toolEventArgs As ESRI.ArcGIS.ADF.Web.UI.WebControls.ToolEventArgs) Implements ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools.IMapServerToolAction.ServerAction
    ' Get the map from the tool arguments
    Dim adfMap As ESRI.ArcGIS.ADF.Web.UI.WebControls.Map = TryCast(toolEventArgs.Control, ESRI.ArcGIS.ADF.Web.UI.WebControls.Map)

    ' Get the user-defined envelope
    Dim mapRectangleEventArgs As ESRI.ArcGIS.ADF.Web.UI.WebControls.MapRectangleEventArgs = TryCast(toolEventArgs, ESRI.ArcGIS.ADF.Web.UI.WebControls.MapRectangleEventArgs)
    Dim adfEnvelope As ESRI.ArcGIS.ADF.Web.Geometry.Envelope = mapRectangleEventArgs.MapExtent

    ' Get the name of the resource containing the active layer.  This is set when a layer on the 
    ' TOC is clicked.  The handler for this is in the code-behind for the SelectionSet page.
    Dim activeResourceName As String = CStr(adfMap.Page.Session("ActiveResourceName"))

    ' Notify the user to select a layer if there is no active resource
    If String.IsNullOrEmpty(activeResourceName) Then
      adfMap.CallbackResults.Add(Me.CreateAlertCallback("Select a layer from the table of contents!"))
      Return
    End If

    ' Get the ID of the active layer
    Dim activeLayerID As String = CStr(adfMap.Page.Session("ActiveLayerID"))

    ' Get the features from the active layer that are within the user-drawn rectangle
    Dim resultsDataTable As System.Data.DataTable = Me.ExecuteQuery(adfMap, activeResourceName, activeLayerID, adfEnvelope)

    ' Notify the user if no features were found
    If resultsDataTable Is Nothing OrElse resultsDataTable.Rows.Count < 1 Then
      adfMap.CallbackResults.Add(Me.CreateAlertCallback("No features selected!"))
      Return
    End If

    ' Convert the results to a GraphicsLayer
    Dim resultsGraphicsLayer As ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsLayer = ESRI.ArcGIS.ADF.Web.UI.WebControls.Converter.ToGraphicsLayer(resultsDataTable)

    ' Enable MapTips and highlighting
    resultsGraphicsLayer.RenderOnClient = True

    ' Get the layer format of the active layer and apply it to the results
    Dim layerFormat As ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerFormat = ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerFormat.FromMapResourceManager(adfMap.MapResourceManagerInstance, activeResourceName, activeLayerID)
    layerFormat.Apply(resultsGraphicsLayer, True)

    ' Zoom the map to the selected features
    adfMap.Extent = resultsGraphicsLayer.FullExtent.Expand(20)

    ' Update the set of selected features
    Me.UpdateSelectedSet(adfMap, resultsGraphicsLayer)

    ' Get the toolbar containing the Select Tool.  Note this code assumes and ID of "Toolbar1."
    Dim adfToolbar As ESRI.ArcGIS.ADF.Web.UI.WebControls.Toolbar = TryCast(adfMap.Page.FindControl("Toolbar1"), ESRI.ArcGIS.ADF.Web.UI.WebControls.Toolbar)

    ' Construct ADF JavaScript to deselect the Select Tool and set the map mode to pan.
    Dim jsToolbarItemDeactivate As String = "" & ControlChars.CrLf & "                    var toolbar = Toolbars['{0}'];" & ControlChars.CrLf & "                    var currentToolField = $get(toolbar.currentToolField);" & ControlChars.CrLf & "                    currentToolField.value = '';" & ControlChars.CrLf & "                    toolbar.selectTool();" & ControlChars.CrLf & "                    toolbar.refreshGroup();" & ControlChars.CrLf & "                    $find('{1}').set_mouseMode(ESRI.ADF.UI.MouseMode.Pan);"
    jsToolbarItemDeactivate = String.Format(jsToolbarItemDeactivate, adfToolbar.ClientID, adfMap.ClientID)

    ' Package the tool manipulation JavaScript in a callback and add it to the map's collection
    Dim deactivateToolbarItemCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsToolbarItemDeactivate)
    adfMap.CallbackResults.Add(deactivateToolbarItemCallbackResult)
  End Sub

  #End Region

  #Region "Private Instance Methods - CreateAlertCallback, ExecuteQuery, UpdateSelectedSet"

  ' Constructs a callback that will display the passed-in text in a JavaScript alert dialog
  Private Function CreateAlertCallback(ByVal alertMessage As String) As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult
    Dim alertScript As String = String.Format("alert('{0}');", alertMessage)
    Return ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(alertScript)
  End Function

  ' Executes a spatial query
  Private Function ExecuteQuery(ByVal adfMap As ESRI.ArcGIS.ADF.Web.UI.WebControls.Map, ByVal resourceName As String, ByVal layerID As String, ByVal queryGeometry As ESRI.ArcGIS.ADF.Web.Geometry.Geometry) As System.Data.DataTable
    ' Get the map functionality for the resource
    Dim mapFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality = adfMap.GetFunctionality(resourceName)

    ' Get the resource and make sure it supports querying
    Dim gisResource As ESRI.ArcGIS.ADF.Web.DataSources.IGISResource = mapFunctionality.Resource
    Dim supportsQueries As Boolean = gisResource.SupportsFunctionality (GetType(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality))
    If (Not supportsQueries) Then
      Return Nothing
    End If

    ' Get query functionality for the resource
    Dim queryFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality = TryCast(gisResource.CreateFunctionality(GetType(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), Nothing), ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)

    ' Initialize a spatial filter with the user-drawn extent
    Dim adfSpatialFilter As ESRI.ArcGIS.ADF.Web.SpatialFilter = New ESRI.ArcGIS.ADF.Web.SpatialFilter()
    adfSpatialFilter.ReturnADFGeometries = True
    adfSpatialFilter.MaxRecords = 1000
    adfSpatialFilter.Geometry = queryGeometry

    ' Get the features within the user-drawn extent
    Return queryFunctionality.Query(mapFunctionality.Name, layerID, adfSpatialFilter)
  End Function

  ' Updates the Selected Set task result node and graphic features with the passed-in graphics layer
  Private Sub UpdateSelectedSet(ByVal adfMap As ESRI.ArcGIS.ADF.Web.UI.WebControls.Map, ByVal resultsGraphicsLayer As ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsLayer)
    ' Get the task results control.  Note this code assumes the existence of a task results
    ' control with an ID of "TaskResults1."
        Dim taskResults As ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults = TryCast(ESRI.ArcGIS.ADF.Web.UI.WebControls.Utility.FindControl("TaskResults1", adfMap.Page), ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults)

    ' Remove the previous selection set node and any selected features
    For Each node As ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode In taskResults.Nodes
      ' Check whether the current node is the selection set node
      If node.Text.StartsWith("Selected Set") Then
        ' Remove the node's features from the map
        Dim mapDisplayNode As ESRI.ArcGIS.ADF.Web.UI.WebControls.MapDisplayNode = TryCast(node.Nodes(0), ESRI.ArcGIS.ADF.Web.UI.WebControls.MapDisplayNode)
        mapDisplayNode.RemoveFromMap(taskResults)

        ' Remove the node
        node.Remove()
        Exit For
      End If
    Next node

    ' Add the results to a new DataSet
    Dim resultsDataSet As System.Data.DataSet = New System.Data.DataSet("Selected Set")
    resultsDataSet.Tables.Add(resultsGraphicsLayer)

    ' Display the results
    taskResults.DisplayResults(Nothing, Nothing, Nothing, resultsDataSet)

    ' Refresh the TaskResults control so the removal of the previous selection set
    ' node is processed
    taskResults.Refresh()

    ' Copy the TaskResults control's callback results to the Map so its updates are 
    ' processed on the client
    adfMap.CallbackResults.CopyFrom(taskResults.CallbackResults)
  End Sub

  #End Region
End Class