Common Task results
Common_TaskResults_CSharp\TaskResultsWebSite\App_Code\SelectTool.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.
// 

// 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.
public class SelectTool : ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools.IMapServerToolAction
{
    #region IMapServerToolAction Members - ServerAction

    void ESRI.ArcGIS.ADF.Web.UI.WebControls.Tools.IMapServerToolAction.ServerAction(
        ESRI.ArcGIS.ADF.Web.UI.WebControls.ToolEventArgs toolEventArgs)
    {
        // Get the map from the tool arguments
        ESRI.ArcGIS.ADF.Web.UI.WebControls.Map adfMap =
            toolEventArgs.Control as ESRI.ArcGIS.ADF.Web.UI.WebControls.Map;

        // Get the user-defined envelope
        ESRI.ArcGIS.ADF.Web.UI.WebControls.MapRectangleEventArgs mapRectangleEventArgs = toolEventArgs as
            ESRI.ArcGIS.ADF.Web.UI.WebControls.MapRectangleEventArgs;
        ESRI.ArcGIS.ADF.Web.Geometry.Envelope adfEnvelope = 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.
        string activeResourceName = (string)adfMap.Page.Session["ActiveResourceName"];
        
        // Notify the user to select a layer if there is no active resource
        if (string.IsNullOrEmpty(activeResourceName))
        {
            adfMap.CallbackResults.Add(this.CreateAlertCallback("Select a layer from the table of contents!"));
            return;
        }

        // Get the ID of the active layer
        string activeLayerID = (string)adfMap.Page.Session["ActiveLayerID"];

        // Get the features from the active layer that are within the user-drawn rectangle
        System.Data.DataTable resultsDataTable = this.ExecuteQuery(adfMap, activeResourceName,
            activeLayerID, adfEnvelope);

        // Notify the user if no features were found
        if (resultsDataTable == null || resultsDataTable.Rows.Count < 1)
        {
            adfMap.CallbackResults.Add(this.CreateAlertCallback("No features selected!"));
            return;
        }

        // Convert the results to a GraphicsLayer
        ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsLayer resultsGraphicsLayer = 
            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
        ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerFormat 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
        this.UpdateSelectedSet(adfMap, resultsGraphicsLayer);

        // Get the toolbar containing the Select Tool.  Note this code assumes and ID of "Toolbar1."
        ESRI.ArcGIS.ADF.Web.UI.WebControls.Toolbar adfToolbar = adfMap.Page.FindControl("Toolbar1") as
            ESRI.ArcGIS.ADF.Web.UI.WebControls.Toolbar;

        // Construct ADF JavaScript to deselect the Select Tool and set the map mode to pan.
        string jsToolbarItemDeactivate = @"
                    var toolbar = Toolbars['{0}'];
                    var currentToolField = $get(toolbar.currentToolField);
                    currentToolField.value = '';
                    toolbar.selectTool();
                    toolbar.refreshGroup();
                    $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
        ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult deactivateToolbarItemCallbackResult =
            ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsToolbarItemDeactivate);
        adfMap.CallbackResults.Add(deactivateToolbarItemCallbackResult);
    }

    #endregion

    #region Private Instance Methods - CreateAlertCallback, ExecuteQuery, UpdateSelectedSet

    // Constructs a callback that will display the passed-in text in a JavaScript alert dialog
    private ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult CreateAlertCallback(string alertMessage)
    {
        string alertScript = string.Format("alert('{0}');", alertMessage);
        return ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(alertScript);
    }

    // Executes a spatial query
    private System.Data.DataTable ExecuteQuery(ESRI.ArcGIS.ADF.Web.UI.WebControls.Map adfMap, string resourceName,
        string layerID, ESRI.ArcGIS.ADF.Web.Geometry.Geometry queryGeometry)
    {
        // Get the map functionality for the resource
        ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality mapFunctionality =
            adfMap.GetFunctionality(resourceName);

        // Get the resource and make sure it supports querying
        ESRI.ArcGIS.ADF.Web.DataSources.IGISResource gisResource = mapFunctionality.Resource;
        bool supportsQueries = gisResource.SupportsFunctionality
            (typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality));
        if (!supportsQueries)
            return null;

        // Get query functionality for the resource
        ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality queryFunctionality =
            gisResource.CreateFunctionality(typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality),
            null) as ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality;

        // Initialize a spatial filter with the user-drawn extent
        ESRI.ArcGIS.ADF.Web.SpatialFilter adfSpatialFilter = 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);
    }

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

        // Remove the previous selection set node and any selected features
        foreach (ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode node in taskResults.Nodes)
        {
            // Check whether the current node is the selection set node
            if (node.Text.StartsWith("Selected Set"))
            {
                // Remove the node's features from the map
                ESRI.ArcGIS.ADF.Web.UI.WebControls.MapDisplayNode mapDisplayNode =
                    node.Nodes[0] as ESRI.ArcGIS.ADF.Web.UI.WebControls.MapDisplayNode;
                mapDisplayNode.RemoveFromMap(taskResults);

                // Remove the node
                node.Remove();
                break;
            }
        }

        // Add the results to a new DataSet
        System.Data.DataSet resultsDataSet = new System.Data.DataSet("Selected Set");
        resultsDataSet.Tables.Add(resultsGraphicsLayer);

        // Display the results
        taskResults.DisplayResults(null, null, null, 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);
    }

    #endregion
}