Common Select Buffer tool
Common_SelectBufferTool_VBNet\App_Code\CustomTools.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
Namespace CustomComponents
  Public Class SelectTool
        Implements ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools.IMapServerToolAction
    #Region "IMapServerToolAction Members"

    Private Sub ServerAction(ByVal toolEventArgs As ESRI.ArcGIS.ADF.Web.UI.WebControls.ToolEventArgs) Implements ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools.IMapServerToolAction.ServerAction
      ' Get a reference to the map control on which the tool was executed
      Dim adfMap As ESRI.ArcGIS.ADF.Web.UI.WebControls.Map = CType(toolEventArgs.Control, ESRI.ArcGIS.ADF.Web.UI.WebControls.Map)

      Try
        ' Set the name of the resource on which to perform the selection
        Dim resourceName As String = "Data Layers"

        Dim selectionLayerName As String = Nothing
        Dim showSelectionInTable As Boolean

        ' Check whether the page request was issued using a callback or a postback.  A callback is used if no
        ' ScriptManager is on the page containing the tool.  Otherwise, a partial postback is used.
        If adfMap.Page.IsCallback Then
          ' Get the callback arguments from the __CALLBACKPARAM argument of the page request parameters
          Dim callbackArgumentsString As String = toolEventArgs.Control.Page.Request.Params("__CALLBACKPARAM")
          Dim callbackArgumentsCollection As System.Collections.Specialized.NameValueCollection = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection(callbackArgumentsString)

          ' Get the value of the selection layer and show in selection table server controls, which were explicitly added to 
          ' the callback arguments via JavaScript in Default.aspx
          selectionLayerName = callbackArgumentsCollection("ddlSelectionLayer")
          showSelectionInTable = Boolean.Parse(callbackArgumentsCollection("chkSelectionInTable"))
        Else
          ' Get the value of the selection layer and show in selection table server controls, which are automatically 
          ' included in postbacks (partial postbacks included) due to their being server controls
          selectionLayerName = adfMap.Page.Request.Params("ddlSelectionLayer")

          ' For the show selection in table checkbox, automatic value is passed as either null (if unchecked) or "on" 
          ' (if checked)
          If adfMap.Page.Request.Params("chkSelectionInTable") Is Nothing Then
            showSelectionInTable = False
          Else
            showSelectionInTable = True
          End If
        End If

        ' Get the map extent of the rectangle drawn on the map
        Dim mapRectangleEventArgs As ESRI.ArcGIS.ADF.Web.UI.WebControls.MapRectangleEventArgs = CType(toolEventArgs, ESRI.ArcGIS.ADF.Web.UI.WebControls.MapRectangleEventArgs)
        Dim adfEnvelope As ESRI.ArcGIS.ADF.Web.Geometry.Envelope = mapRectangleEventArgs.MapExtent

        ' Get a reference to the resource
        Dim commonMapFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality = adfMap.GetFunctionality(resourceName)
        Dim gisResource As ESRI.ArcGIS.ADF.Web.DataSources.IGISResource = commonMapFunctionality.Resource

        ' Create a query functionality to use in querying the resource
        Dim commonQueryFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality = CType(gisResource.CreateFunctionality(GetType(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), Nothing), ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)

        ' Get the resource's queryable layers
        Dim layerIDs As String() = Nothing
        Dim layerNames As String() = Nothing
        commonQueryFunctionality.GetQueryableLayers(Nothing, layerIDs, layerNames)

        ' Get the index of the selection layer in the layer names and ids arrays
        Dim selectionLayerIndex As Integer = 0
        Dim i As Integer = 0
        Do While i < layerNames.Length
          If layerNames(i) = selectionLayerName Then
            If TypeOf layerIDs(i) Is String Then
              If (Not Integer.TryParse(CStr(layerIDs(i)), selectionLayerIndex)) Then
                selectionLayerIndex = i
              End If
            Else
              selectionLayerIndex = i
            End If
            Exit Do
          End If
          i += 1
        Loop

        ' Set-up a spatial filter to use in querying the resource
        Dim adfSpatialFilter As ESRI.ArcGIS.ADF.Web.SpatialFilter = New ESRI.ArcGIS.ADF.Web.SpatialFilter()
        adfSpatialFilter.ReturnADFGeometries = True
        adfSpatialFilter.MaxRecords = 100
        adfSpatialFilter.Geometry = adfEnvelope

        ' Query the selection layer with the user-drawn rectangle
        Dim resultsDataTable As System.Data.DataTable = commonQueryFunctionality.Query(commonMapFunctionality.Name, layerIDs(selectionLayerIndex), adfSpatialFilter)

                If resultsDataTable.Rows.Count = 0 Then
                    Dim noFeaturesFoundCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript("alert('No selected features');")
                    adfMap.CallbackResults.Add(noFeaturesFoundCallbackResult)
                End If

        ' Convert the results data table to a graphics layer
        Dim resultsGraphicsLayer As ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsLayer = ESRI.ArcGIS.ADF.Web.Converter.ToGraphicsLayer(resultsDataTable, System.Drawing.Color.Yellow, System.Drawing.Color.Green)

        ' Retrieve and clear buffer resource
        Dim gisFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IGISFunctionality = adfMap.GetFunctionality("Buffer")
        Dim bufferGraphicsMapResource As ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource = TryCast(gisFunctionality.Resource, ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource)
        bufferGraphicsMapResource.Graphics.Tables.Clear()

        ' Retrieve and clear selection resource
        gisFunctionality = adfMap.GetFunctionality("Selection")
        Dim selectionGraphicsMapResource As ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource = TryCast(gisFunctionality.Resource, ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource)
        selectionGraphicsMapResource.Graphics.Tables.Clear()

        ' Add the selection graphics layer to the resource
        selectionGraphicsMapResource.Graphics.Tables.Add(resultsGraphicsLayer)

        ' Call method to display or hide the selection table, depending on whether
        ' the "Display selection in table" checkbox is checked or not
        CustomToolUtility.DisplayOrHideSelectionTable(adfMap, resultsGraphicsLayer, showSelectionInTable)

        ' Set the transparency of the selection graphics resource map resource item
        Dim selectionMapResourceItem As ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceItem = adfMap.MapResourceManagerInstance.ResourceItems.Find(selectionGraphicsMapResource.Name)
        selectionMapResourceItem.DisplaySettings.Transparency = 50

        ' Refresh the selection and buffer resources
        adfMap.RefreshResource(selectionGraphicsMapResource.Name)
        adfMap.RefreshResource(bufferGraphicsMapResource.Name)
      Catch exception As System.Exception
        adfMap.CallbackResults.Add(Utility.GetErrorCallback(exception))
      End Try
    End Sub
    #End Region
  End Class

  Public Class BufferTool
        Implements ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools.IMapServerToolAction
    #Region "IMapServerToolAction Members"

    Private Sub ServerAction(ByVal toolEventArgs As ESRI.ArcGIS.ADF.Web.UI.WebControls.ToolEventArgs) Implements ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools.IMapServerToolAction.ServerAction
      Dim adfMap As ESRI.ArcGIS.ADF.Web.UI.WebControls.Map = CType(toolEventArgs.Control, ESRI.ArcGIS.ADF.Web.UI.WebControls.Map)

      Try
        Dim mapPointEventArgs As ESRI.ArcGIS.ADF.Web.UI.WebControls.MapPointEventArgs = CType(toolEventArgs, ESRI.ArcGIS.ADF.Web.UI.WebControls.MapPointEventArgs)
        Dim adfPoint As ESRI.ArcGIS.ADF.Web.Geometry.Point = mapPointEventArgs.MapPoint

        Dim bufferDistanceString As String = Nothing
        Dim selectionLayerName As String = Nothing
        Dim showSelectionInTable As Boolean

        ' Check whether the page request was issued using a callback or a postback.  A callback is used if no
        ' ScriptManager is on the page containing the tool.  Otherwise, a partial postback is used.
        If adfMap.Page.IsCallback Then
          ' Get the callback arguments from the __CALLBACKPARAM argument of the page request parameters
          Dim callbackArgumentsString As String = toolEventArgs.Control.Page.Request.Params("__CALLBACKPARAM")
          Dim callbackArgumentsCollection As System.Collections.Specialized.NameValueCollection = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection(callbackArgumentsString)

          ' Get the value of the buffer distance, selection layer, and show in selection table server controls, which were
          ' explicitly added to the tool's arguments via JavaScript in Default.aspx
          bufferDistanceString = callbackArgumentsCollection("txtBufferDistance")
          selectionLayerName = callbackArgumentsCollection("ddlSelectionLayer")
          showSelectionInTable = Boolean.Parse(callbackArgumentsCollection("chkSelectionInTable"))
        Else
          ' Get the value of the buffer distance, selection layer, and show in selection table server controls, which are 
          ' automatically included in postbacks (partial postbacks included) due to their being server controls
          bufferDistanceString = adfMap.Page.Request.Params("txtBufferDistance")
          selectionLayerName = adfMap.Page.Request.Params("ddlSelectionLayer")

          ' For the show selection in table checkbox, automatic value is passed as either null (if unchecked) or "on" 
          ' (if checked)
          If adfMap.Page.Request.Params("chkSelectionInTable") Is Nothing Then
            showSelectionInTable = False
          Else
            showSelectionInTable = True
          End If
        End If

        ' Attempt to retrieve buffer distance from session.  If the attempt fails, initialize
        ' buffer distance as 0.
        Dim bufferDistanceFloat As Single
        If (Not System.Single.TryParse(bufferDistanceString, bufferDistanceFloat)) Then
          bufferDistanceFloat = 0.0F
        End If

        ' Create an ellipse based on the buffer distance
        Dim graphicsPath As System.Drawing.Drawing2D.GraphicsPath = New System.Drawing.Drawing2D.GraphicsPath()
        graphicsPath.AddEllipse(CSng(adfPoint.X) - (bufferDistanceFloat / 2), CSng(adfPoint.Y) - (bufferDistanceFloat / 2), bufferDistanceFloat, bufferDistanceFloat)

        ' Flatten the ellipse.  This will make it appear smooth.
        Dim flattening As Single = bufferDistanceFloat / 1000
        graphicsPath.Flatten(Nothing, flattening)

        ' Create a Web ADF Point Collection, and add each point in the graphics path to it
        Dim adfPointCollection As ESRI.ArcGIS.ADF.Web.Geometry.PointCollection = New ESRI.ArcGIS.ADF.Web.Geometry.PointCollection()
        For Each pointF As System.Drawing.PointF In graphicsPath.PathPoints
          adfPointCollection.Add(New ESRI.ArcGIS.ADF.Web.Geometry.Point(pointF.X, pointF.Y))
        Next pointF

        ' Construct a Web ADF Polygon containing the buffer by populating a ring with the 
        ' buffer point collection, a ring collection with the ring, and a polygon with the 
        ' ring collection
        Dim adfRing As ESRI.ArcGIS.ADF.Web.Geometry.Ring = New ESRI.ArcGIS.ADF.Web.Geometry.Ring()
        adfRing.Points = adfPointCollection
        Dim adfRingCollection As ESRI.ArcGIS.ADF.Web.Geometry.RingCollection = New ESRI.ArcGIS.ADF.Web.Geometry.RingCollection()
        adfRingCollection.Add(adfRing)
        Dim adfBufferPolygon As ESRI.ArcGIS.ADF.Web.Geometry.Polygon = New ESRI.ArcGIS.ADF.Web.Geometry.Polygon()
        adfBufferPolygon.Rings = adfRingCollection

        ' Get the graphics resource that will hold the buffer
        Dim gisFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IGISFunctionality = adfMap.GetFunctionality("Buffer")
        Dim bufferGraphicsMapResource As ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource = TryCast(gisFunctionality.Resource, ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource)

        ' If the resource was not found, throw an exception
        If bufferGraphicsMapResource Is Nothing Then
          Throw New System.Exception("Buffer graphics resource not in MapResourceManager")
        End If

        ' Clear the buffer resource of any previous results
        bufferGraphicsMapResource.Graphics.Tables.Clear()

        ' Add an element graphics layer to store the buffer geometry to the resource
        Dim elementGraphicsLayer As ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer = New ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer()
        bufferGraphicsMapResource.Graphics.Tables.Add(elementGraphicsLayer)

        ' Create a graphic element out of the buffer polygon and add it to the 
        ' buffer graphics layer
        Dim adfGeometry As ESRI.ArcGIS.ADF.Web.Geometry.Geometry = CType(adfBufferPolygon, ESRI.ArcGIS.ADF.Web.Geometry.Geometry)
        Dim graphicElement As ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicElement = New ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicElement(adfGeometry, System.Drawing.Color.Green)
        graphicElement.Symbol.Transparency = 70.0
        elementGraphicsLayer.Add(graphicElement)

        ' Get the resource containing the selection layer
        Dim commonMapFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality = adfMap.GetFunctionality("Data Layers")
        Dim gisResource As ESRI.ArcGIS.ADF.Web.DataSources.IGISResource = commonMapFunctionality.Resource

        ' Create a query functionality and use it to retrieve the IDs and names of the
        ' resource's queryable layers
        Dim commonQueryFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality = CType(gisResource.CreateFunctionality(GetType(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), Nothing), ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)

        Dim layerIDs As String()
        Dim layerNames As String()
        commonQueryFunctionality.GetQueryableLayers(Nothing, layerIDs, layerNames)

        ' Get the index of the selection layer in the ID and names arrays
        Dim selectionLayerIndex As Integer = 0
        Dim i As Integer = 0
        Do While i < layerNames.Length
          If layerNames(i) = selectionLayerName Then
            selectionLayerIndex = i
            Exit Do
          End If
          i += 1
        Loop

        ' Initialize a Web ADF spatial filter with the buffer geometry and use
        ' it to query the resource on which the selection will be performed
        Dim adfSpatialFilter As ESRI.ArcGIS.ADF.Web.SpatialFilter = New ESRI.ArcGIS.ADF.Web.SpatialFilter()
        adfSpatialFilter.ReturnADFGeometries = True
        adfSpatialFilter.MaxRecords = 1000
        adfSpatialFilter.Geometry = adfBufferPolygon
        Dim featuresInBufferDataTable As System.Data.DataTable = commonQueryFunctionality.Query(Nothing, layerIDs(selectionLayerIndex), adfSpatialFilter)

                If featuresInBufferDataTable.Rows.Count = 0 Then
                    Dim noFeaturesFoundCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript("alert('No selected features');")
                    adfMap.CallbackResults.Add(noFeaturesFoundCallbackResult)
                End If
        ' Convert the query results to a graphics layer
        Dim selectionGraphicsLayer As ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsLayer = ESRI.ArcGIS.ADF.Web.Converter.ToGraphicsLayer(featuresInBufferDataTable, System.Drawing.Color.Yellow, System.Drawing.Color.Yellow)

        ' Get the graphics resource that will hold the selection and add the selection
        ' graphics layer to it
        gisFunctionality = adfMap.GetFunctionality("Selection")
        Dim selectionGraphicsMapResource As ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource = TryCast(gisFunctionality.Resource, ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource)
        selectionGraphicsMapResource.Graphics.Tables.Clear()
        selectionGraphicsMapResource.Graphics.Tables.Add(selectionGraphicsLayer)

        CustomToolUtility.DisplayOrHideSelectionTable(adfMap, selectionGraphicsLayer, showSelectionInTable)

        ' Set the transparency of the buffer graphics resource map resource item
        Dim bufferMapResourceItem As ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceItem = adfMap.MapResourceManagerInstance.ResourceItems.Find(bufferGraphicsMapResource.Name)
        bufferMapResourceItem.DisplaySettings.Transparency = 50

        ' Set the transparency of the selection graphics resource map resource item
        Dim selectionMapResourceItem As ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceItem = adfMap.MapResourceManagerInstance.ResourceItems.Find(selectionGraphicsMapResource.Name)
        selectionMapResourceItem.DisplaySettings.Transparency = 50

        adfMap.RefreshResource(bufferGraphicsMapResource.Name)
        adfMap.RefreshResource(selectionGraphicsMapResource.Name)

      Catch exception As System.Exception
        adfMap.CallbackResults.Add(Utility.GetErrorCallback(exception))
      End Try
    End Sub
    #End Region
  End Class

  Friend Class CustomToolUtility
    Public Shared Sub DisplayOrHideSelectionTable(ByVal adfMap As ESRI.ArcGIS.ADF.Web.UI.WebControls.Map, ByVal resultsGraphicsLayer As ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsLayer, ByVal showTable As Boolean)
      Try

        ' Get the GridView control that will be used to display selection results
        Dim gridViewResults As System.Web.UI.WebControls.GridView = CType(adfMap.Page.FindControl("grdSelectionResults"), System.Web.UI.WebControls.GridView)
                Dim updatepanel As System.Web.UI.UpdatePanel = CType(adfMap.Page.FindControl("UpdatePanel1"), System.Web.UI.UpdatePanel)
        Dim resultsDataTable As System.Data.DataTable = resultsGraphicsLayer

        ' Check whether to show selection results tabularly
        If showTable Then
          ' Make sure results were actually found
          If resultsDataTable.Rows.Count > 0 Then
            ' Load the graphicsLayer into a new data table and remove the IS_SELECTED column
            Dim newDataTable As System.Data.DataTable = New System.Data.DataTable()
            newDataTable.Load(resultsGraphicsLayer.CreateDataReader())
            newDataTable.Columns.Remove("IS_SELECTED")

            ' Bind the results table to the GridView control
            gridViewResults.DataSource = newDataTable
            gridViewResults.DataBind()

                        gridViewResults.Visible = True
          Else
            ' Create a callback result to update the content of the selection results div
                        ' with a message informing the user that no features were selected.
                        gridViewResults.Visible = False
            
          End If

          
        Else
                    gridViewResults.Visible = False
                End If
                updatepanel.Update()
      Catch exception As System.Exception
        adfMap.CallbackResults.Add(Utility.GetErrorCallback(exception))
      End Try
    End Sub
  End Class
End Namespace