ArcIMS Select Buffer tool
ArcIMS_SelectBufferTool_CSharp\Default.aspx.cs
// 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.
// 



using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Collections;

public partial class _Default : System.Web.UI.Page, System.Web.UI.ICallbackEventHandler
{
    private string m_ADFCallbackFunctionString;
    private ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResultCollection m_ADFCallbackResultCollection;
    private int m_ResourceIndex = 0;
    private System.Collections.Specialized.NameValueCollection m_NameValueCollection;

    // ICallbackEventHandler implementation
    public void RaiseCallbackEvent(string eventArgs)
    {
        m_ADFCallbackResultCollection =
            new ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResultCollection();

        m_NameValueCollection = ESRI.ArcGIS.ADF.Web.UI.WebControls.
            CallbackUtility.ParseStringIntoNameValueCollection(eventArgs);
        string eventArg = m_NameValueCollection["EventArg"];

        if (eventArg.Equals("selectButton"))
        {
            // Only select features, no buffer
            SelectionToolSelectAndBuffer(false);
        }
        else if (eventArg.Equals("bufferSelectButton"))
        {
            // Buffer and select from target layer, if set
            SelectionToolSelectAndBuffer(true);
        }
        else if (eventArg.Equals("clearAllButton") || eventArg.Equals("activeLayerDropDownList"))
        {
            // Clear all dynamic layers and refresh map resource
            ClearAllLayers(true);
        }
    }

    public string GetCallbackResult()
    {
        return m_ADFCallbackResultCollection.ToString();
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        // Generate custom callback function string for html buttons and active layer drop down list
        // Page will process callback.
        m_ADFCallbackFunctionString = Page.ClientScript.GetCallbackEventReference(this, "message", "processCallbackResult", "context", "postBackError", true);
        // Upon change of active layer, map will clear all dynamic layers.
        activeLayerDropDownList.Attributes.Add("onchange", "CustomCallback(this.id)");
    }

    protected void Page_PreRender(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            // On initial prerender, update dropdown lists with layer names and unit options
            ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality mapFunctionality = (ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality)Map1.GetFunctionality(m_ResourceIndex);
            ESRI.ArcGIS.ADF.Web.DataSources.IGISResource gisResource = mapFunctionality.Resource;
            bool supported = gisResource.SupportsFunctionality(typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality));

            if (supported)
            {
                ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality queryFunctionality = (ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)gisResource.CreateFunctionality(typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), null);

                string[] layerIDs = null;
                string[] layerNames = null;
                queryFunctionality.GetQueryableLayers(null, out layerIDs, out layerNames);

                selectLayerDropDownList.Items.Add("none");
                bufferSelectLayerDropDownList.Items.Add("none");
                for (int i = 0; i < layerNames.Length; i++)
                {
                    activeLayerDropDownList.Items.Add(layerNames[i]);
                    selectLayerDropDownList.Items.Add(layerNames[i]);
                    bufferSelectLayerDropDownList.Items.Add(layerNames[i]);
                }
            }

            Array imsBufferUnits = Enum.GetValues(typeof(ESRI.ArcGIS.ADF.IMS.Carto.Layer.BufferUnits));
            foreach (int imsBufferUnit in imsBufferUnits)
            {
                bufferToolUnitsDropDownList.Items.Add(imsBufferUnits.GetValue(imsBufferUnit).ToString());
                bufferActiveUnitsDropDownList.Items.Add(imsBufferUnits.GetValue(imsBufferUnit).ToString());
            }
        }

        // On load of page content in the browser, execute some JavaScript to add custom element parameters to all 
        // Web ADF postbacks.  Also, create a custom JavaScript function to initiate custom callback to the page and
        // package element values.  
        string scriptKeyCustom = "customChangeScript";
        if (!this.Page.ClientScript.IsClientScriptBlockRegistered(GetType(), scriptKeyCustom) && !Page.IsPostBack)
        {
            string scriptBlock = @"
                
                function onLoadFunction() {
                    var theform = document.forms[0];
                    var original_value = theform.elements[""ESRIWebADFHiddenFields""].value;
                    var new_value = original_value + "",{0},{1},{2},{3}"";
                    theform.elements[""ESRIWebADFHiddenFields""].value = new_value;    
                }

                function CustomCallback(argument){
                    var message = ""EventArg="" + argument + ""&"";
                    message += ""{0}="" + document.getElementById('{0}').value + ""&"";
                    message += ""{4}="" + document.getElementById('{4}').value + ""&"";
                    message += ""{5}="" + document.getElementById('{5}').value + ""&"";
                    message += ""{6}="" + document.getElementById('{6}').value;
                    var context = null;
                  {7}
                }
 
                ";

            scriptBlock = scriptBlock.Replace("{0}", activeLayerDropDownList.UniqueID);
            scriptBlock = scriptBlock.Replace("{1}", bufferToolDistanceTextBox.UniqueID);
            scriptBlock = scriptBlock.Replace("{2}", bufferToolUnitsDropDownList.UniqueID);
            scriptBlock = scriptBlock.Replace("{3}", bufferSelectLayerDropDownList.UniqueID);

            scriptBlock = scriptBlock.Replace("{4}", selectLayerDropDownList.UniqueID);
            scriptBlock = scriptBlock.Replace("{5}", bufferActiveDistanceTextBox.UniqueID);
            scriptBlock = scriptBlock.Replace("{6}", bufferActiveUnitsDropDownList.UniqueID);

            scriptBlock = scriptBlock.Replace("{7}", m_ADFCallbackFunctionString);

            this.Page.ClientScript.RegisterClientScriptBlock(GetType(), scriptKeyCustom, scriptBlock, true);
        }

        string scriptKey = "loadScript";
        if (!this.Page.ClientScript.IsClientScriptBlockRegistered(GetType(), scriptKey) && !Page.IsPostBack)
        {
            // if Mozilla browser, use DOMContentLoaded event, else add to body onload
            string scriptBlock = @"
                if (document.addEventListener) {    
                    document.addEventListener(""DOMContentLoaded"", onLoadFunction , false);
                } else {
                    top.document.body.onload = onLoadFunction;
                }
                                ";
            this.Page.ClientScript.RegisterClientScriptBlock(GetType(), scriptKey, scriptBlock, true);
        }
    }

    private void ClearAllLayers(bool initialCallback)
    {
        ESRI.ArcGIS.ADF.Web.DataSources.IMS.MapFunctionality imsMapFunctionality = (ESRI.ArcGIS.ADF.Web.DataSources.IMS.MapFunctionality)Map1.GetFunctionality(m_ResourceIndex);
        ESRI.ArcGIS.ADF.IMS.Carto.MapView mapView = imsMapFunctionality.MapView;

        foreach (string layerName in LayerNames.GetLayerNames())
        {
            ESRI.ArcGIS.ADF.IMS.Carto.Layer.Layer layer =
                mapView.Layers.FindByName(layerName);
            if (layer != null)
            {
                if (layer.Name == LayerNames.SelectionToolActive)
                {
                    // Remove active selection layer and filter from session if 
                    // the clearAllButton button is pressed.  Otherwise, keep active 
                    // selection layer.
                    if (initialCallback)
                    {
                        Session["activeLayerFilter"] = null;
                        mapView.Layers.Remove(layer);
                    }
                }
                else
                {
                    mapView.Layers.Remove(layer);
                }
            }
        }

        // Only refresh Map and return callback response if the clearAllButton button is pressed.
        if (initialCallback)
        {

            if (Map1.ImageBlendingMode == ESRI.ArcGIS.ADF.Web.UI.WebControls.ImageBlendingMode.Browser)
            {
                Map1.RefreshResource(imsMapFunctionality.Resource.Name);
            }
            else
            {
                Map1.Refresh();
            }
            m_ADFCallbackResultCollection.CopyFrom(Map1.CallbackResults);
        }

    }

    // For ArcMap services, all dynamic feature layers must have a null renderer.  
    // Renderers are defined in the mxd document.  Each feature layer can define its own selection renderer. 
    // Buffers on feature layers use the default selection color for the data frame.  
    private void SelectionToolSelectAndBuffer(bool bufferAndSelect)
    {
        // Get argument values from client.  Popluated in RaiseCallbackEvent() method.
        string activeLayerName = m_NameValueCollection["activeLayerDropDownList"];
        string targetLayerName = m_NameValueCollection["selectLayerDropDownList"];
        string bufferDistanceString = m_NameValueCollection["bufferActiveDistanceTextBox"];
        string bufferUnitsString = m_NameValueCollection["bufferActiveUnitsDropDownList"];

        ESRI.ArcGIS.ADF.Web.DataSources.IMS.MapFunctionality imsMapFunctionality =
            (ESRI.ArcGIS.ADF.Web.DataSources.IMS.MapFunctionality)Map1.GetFunctionality(m_ResourceIndex);

        ESRI.ArcGIS.ADF.IMS.Carto.MapView mapview = imsMapFunctionality.MapView;
        ESRI.ArcGIS.ADF.IMS.Carto.Layer.LayerCollection imsLayerCollection = mapview.Layers;

        // Clear dynamic layers (selections, buffers, IMS acetate layers) except active layer selection
        ClearAllLayers(false);

        ESRI.ArcGIS.ADF.IMS.Carto.Layer.FeatureLayer activeLayer =
            (ESRI.ArcGIS.ADF.IMS.Carto.Layer.FeatureLayer)imsLayerCollection.FindByName(activeLayerName);

        // Get the filter applied by the selection tool on the active layer
        ESRI.ArcGIS.ADF.IMS.Carto.Layer.Filter activeLayerFilter =
            (ESRI.ArcGIS.ADF.IMS.Carto.Layer.Filter)Session["activeLayerFilter"];

        // If target layer is set, get it
        ESRI.ArcGIS.ADF.IMS.Carto.Layer.FeatureLayer targetLayer = null;
        if (targetLayerName != "none")
        {
            targetLayer = (ESRI.ArcGIS.ADF.IMS.Carto.Layer.FeatureLayer)
                imsLayerCollection.FindByName(targetLayerName);
        }

        // Default buffer distance of 0, unless explicitly set in a request.
        float bufferDistance;
        if (!Single.TryParse(bufferDistanceString, out bufferDistance))
        {
            bufferDistance = 0.0F;
        }

        // Default buffer units of Decimal Degrees, unless explicitly set in a request.
        // As an enumeration, this is only a placeholder.  The default of Decimal Degrees
        // is only used when buffering polygons and the distance is 0.
        ESRI.ArcGIS.ADF.IMS.Carto.Layer.BufferUnits imsBufferUnits =
            ESRI.ArcGIS.ADF.IMS.Carto.Layer.BufferUnits.Decimal_Degrees;

        if (bufferAndSelect)
        {
            // Get buffer units from user
            imsBufferUnits = (ESRI.ArcGIS.ADF.IMS.Carto.Layer.BufferUnits)
                Enum.Parse(typeof(ESRI.ArcGIS.ADF.IMS.Carto.Layer.BufferUnits),
                bufferUnitsString, true);

            // Draw the buffer 
            ESRI.ArcGIS.ADF.IMS.Carto.Layer.DisplayBuffer displayBuffer =
                new ESRI.ArcGIS.ADF.IMS.Carto.Layer.DisplayBuffer();
            displayBuffer.Distance = bufferDistance;
            displayBuffer.Units = imsBufferUnits;

            // Construct dynamic buffer feature layer.  ArcMap services require a null renderer.
            ESRI.ArcGIS.ADF.IMS.Carto.Layer.FeatureLayer bufferLayer = null;

            if (imsMapFunctionality.MapResource.MapService.Type == ESRI.ArcGIS.ADF.IMS.ServiceType.ArcMapServer)
            {
                bufferLayer = activeLayer.CreateBufferLayer(activeLayerFilter, displayBuffer,
                    null, LayerNames.SelectionToolBuffer);
            }
            else
            {
                // Renderer for buffer, always a polygon
                ESRI.ArcGIS.ADF.IMS.Display.Renderer.SimpleRenderer bufferSimpleRenderer =
                    new ESRI.ArcGIS.ADF.IMS.Display.Renderer.SimpleRenderer();
                ESRI.ArcGIS.ADF.IMS.Display.Symbol.SimpleFillSymbol bufferSimpleFillSymbol =
                    new ESRI.ArcGIS.ADF.IMS.Display.Symbol.SimpleFillSymbol();
                bufferSimpleFillSymbol.Color = System.Drawing.Color.Green;
                
                // Transparency in percent instead of 0-1
                bufferSimpleFillSymbol.Transparency = 50.0;
                bufferSimpleRenderer.Symbol = bufferSimpleFillSymbol;

                bufferLayer = activeLayer.CreateBufferLayer(activeLayerFilter, displayBuffer,
                    bufferSimpleRenderer, LayerNames.SelectionToolBuffer);
            }
            bufferLayer.Name = LayerNames.SelectionToolBuffer;
            
            // *** Add dynamic buffer layer to the map
            mapview.Layers.Add(bufferLayer);
        }

        // If selecting feature in a target layer, the following code executes
        if (targetLayer != null)
        {
            // Create a layer to store the selected features in the target layer 
            ESRI.ArcGIS.ADF.IMS.Carto.Layer.FeatureLayer targetSelectionLayer = null;
            
            // In ArcIMS, all feature layers of geometry type point, line, or polygon can be buffered using a value
            // great than 0.  Only feature layers of type polygon can be buffered using a distance of 0 
            // (essentially a layer on layer selection).   So if the buffer distance is greater than 0 or the feature 
            // type is polygon, a buffer can be constructed to select features in a target layer.
            if (bufferDistance > 0 || activeLayer.Type == ESRI.ArcGIS.ADF.IMS.FeatureType.Polygon)
            {                
                ESRI.ArcGIS.ADF.IMS.Carto.Layer.SelectionBuffer activeLayerSelectionBuffer =
                    new ESRI.ArcGIS.ADF.IMS.Carto.Layer.SelectionBuffer(targetLayer, string.Empty);
                
                // If bufferSelectButton is pressed
                if (bufferAndSelect)
                {
                    activeLayerSelectionBuffer.Distance = bufferDistance;
                    activeLayerSelectionBuffer.Units = imsBufferUnits;
                }
                else // Only used if the active layer is of type polygon
                {
                    activeLayerSelectionBuffer.Distance = 0;
                    activeLayerSelectionBuffer.Units =
                        ESRI.ArcGIS.ADF.IMS.Carto.Layer.BufferUnits.Decimal_Degrees;
                }

                if (imsMapFunctionality.MapResource.MapService.Type == ESRI.ArcGIS.ADF.IMS.ServiceType.ArcMapServer)
                {
                    targetSelectionLayer = activeLayer.CreateBufferSelectionLayer(activeLayerFilter,
                        activeLayerSelectionBuffer, null, LayerNames.SelectionToolTarget);
                }
                else
                {
                    targetSelectionLayer = activeLayer.CreateBufferSelectionLayer(activeLayerFilter,
                        activeLayerSelectionBuffer, SelectionToolTargetLayerRenderer(targetLayer.Type), LayerNames.SelectionToolTarget);
                }
            }
            else // If buffer distance is 0 and active layer is of type point or line
            {
                
                // Construct a query to return feature geometry selected in the active layer
                ESRI.ArcGIS.ADF.IMS.Carto.Layer.QueryParameters activeLayerQueryParameters =
                    new ESRI.ArcGIS.ADF.IMS.Carto.Layer.QueryParameters(activeLayerFilter);
                activeLayerQueryParameters.ReturnGeometries = true;
                ESRI.ArcGIS.ADF.IMS.Carto.Layer.FeatureTable activeLayerQueryFeatureTable =
                    activeLayer.Query(activeLayerQueryParameters);
                
                // Find the shape field               
                int shapeFieldIndex = -1;
                for (int index = 0; index < activeLayerQueryFeatureTable.Columns.Count; index++)
                {
                    if (activeLayerQueryFeatureTable.Columns[index].DataType ==
                        typeof(ESRI.ArcGIS.ADF.IMS.Geometry.Geometry))
                    {
                        shapeFieldIndex = index;
                        break;
                    }
                }

                // Package the selected feature geometry in a simple Multipoint or Polyline used to create
                // a selection layer
                ESRI.ArcGIS.ADF.IMS.Geometry.Geometry imsGeometry = null;

                if (activeLayer.Type == ESRI.ArcGIS.ADF.IMS.FeatureType.Point)
                {
                    ESRI.ArcGIS.ADF.IMS.Geometry.Multipoint imsSelectionMultipoint =
                        new ESRI.ArcGIS.ADF.IMS.Geometry.Multipoint();
                    foreach (DataRow dataRow in activeLayerQueryFeatureTable.Rows)
                    {
                        ESRI.ArcGIS.ADF.IMS.Geometry.Multipoint imsFeatureMultipoint =
                            (ESRI.ArcGIS.ADF.IMS.Geometry.Multipoint)dataRow[shapeFieldIndex];
                        foreach (ESRI.ArcGIS.ADF.IMS.Geometry.Point imsPoint in imsFeatureMultipoint.Points)
                        {
                            imsSelectionMultipoint.Points.Add(imsPoint);
                        }
                    }
                    imsGeometry = imsSelectionMultipoint;
                }
                else if (activeLayer.Type == ESRI.ArcGIS.ADF.IMS.FeatureType.Line)
                {
                    ESRI.ArcGIS.ADF.IMS.Geometry.Polyline imsSelectionPolyline =
                        new ESRI.ArcGIS.ADF.IMS.Geometry.Polyline();
                    foreach (DataRow dataRow in activeLayerQueryFeatureTable.Rows)
                    {
                        ESRI.ArcGIS.ADF.IMS.Geometry.Polyline imsFeaturePolyline =
                            (ESRI.ArcGIS.ADF.IMS.Geometry.Polyline)dataRow[shapeFieldIndex];
                        foreach (ESRI.ArcGIS.ADF.IMS.Geometry.Path imsPath in imsFeaturePolyline.Paths)
                        {
                            imsSelectionPolyline.Paths.Add(imsPath);
                        }
                    }
                    imsGeometry = imsSelectionPolyline;
                }

                // Create a filter to select features in the target layer
                activeLayerFilter = new ESRI.ArcGIS.ADF.IMS.Carto.Layer.Filter();
                activeLayerFilter.Geometry = imsGeometry;

                if (imsMapFunctionality.MapResource.MapService.Type == ESRI.ArcGIS.ADF.IMS.ServiceType.ArcMapServer)
                {
                    targetSelectionLayer = targetLayer.CreateSelectionLayer(activeLayerFilter,
                        null, LayerNames.SelectionToolTarget);
                }
                else
                {
                    targetSelectionLayer = targetLayer.CreateSelectionLayer(activeLayerFilter,
                        SelectionToolTargetLayerRenderer(targetLayer.Type), LayerNames.SelectionToolTarget);
                }
            }

            targetSelectionLayer.Name = LayerNames.SelectionToolTarget;
            // *** Add dynamic selection from the target layer to the map
            mapview.Layers.Add(targetSelectionLayer);
        }

        if (Map1.ImageBlendingMode == ESRI.ArcGIS.ADF.Web.UI.WebControls.ImageBlendingMode.Browser)
        {
            Map1.RefreshResource(imsMapFunctionality.Resource.Name);
        }
        else
        {
            Map1.Refresh();
        }

        m_ADFCallbackResultCollection.CopyFrom(Map1.CallbackResults);
    }

    // Create a renderer for the selected features in the target layer defined in the SelectionTool
    private ESRI.ArcGIS.ADF.IMS.Display.Renderer.SimpleRenderer SelectionToolTargetLayerRenderer
        (ESRI.ArcGIS.ADF.IMS.FeatureType targetFeatureType)
    {
        ESRI.ArcGIS.ADF.IMS.Display.Renderer.SimpleRenderer targetSelectionSimpleRenderer =
            new ESRI.ArcGIS.ADF.IMS.Display.Renderer.SimpleRenderer();

        ESRI.ArcGIS.ADF.IMS.Display.Symbol.FeatureSymbol targetSelectionFeatureSymbol = null;

        if (targetFeatureType == ESRI.ArcGIS.ADF.IMS.FeatureType.Point)
        {
            ESRI.ArcGIS.ADF.IMS.Display.Symbol.SimpleMarkerSymbol targetSelectionSimpleMarkerSymbol =
                new ESRI.ArcGIS.ADF.IMS.Display.Symbol.SimpleMarkerSymbol();
            targetSelectionSimpleMarkerSymbol.Color = System.Drawing.Color.Red;
            targetSelectionSimpleMarkerSymbol.Width = 8;
            targetSelectionFeatureSymbol = targetSelectionSimpleMarkerSymbol;
        }
        else if (targetFeatureType == ESRI.ArcGIS.ADF.IMS.FeatureType.Line)
        {
            ESRI.ArcGIS.ADF.IMS.Display.Symbol.SimpleLineSymbol targetSelectionSimpleLineSymbol =
                new ESRI.ArcGIS.ADF.IMS.Display.Symbol.SimpleLineSymbol();
            targetSelectionSimpleLineSymbol.Width = 2;
            targetSelectionSimpleLineSymbol.Color = System.Drawing.Color.Red;
            targetSelectionFeatureSymbol = targetSelectionSimpleLineSymbol;
        }
        else if (targetFeatureType == ESRI.ArcGIS.ADF.IMS.FeatureType.Polygon)
        {
            ESRI.ArcGIS.ADF.IMS.Display.Symbol.SimpleFillSymbol targetSelectionSimpleFillSymbol =
                new ESRI.ArcGIS.ADF.IMS.Display.Symbol.SimpleFillSymbol();
            targetSelectionSimpleFillSymbol.Color = System.Drawing.Color.Red;
            targetSelectionFeatureSymbol = targetSelectionSimpleFillSymbol;
        }

        if (targetSelectionFeatureSymbol != null)
        {
            targetSelectionFeatureSymbol.Transparency = 50.0;
        }

        targetSelectionSimpleRenderer.Symbol = targetSelectionFeatureSymbol;

        return targetSelectionSimpleRenderer;
    }
}