Common_CustomTasks_CSharp\FindNearTask_CSharp\FindNearTask.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. // // Embedded images [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.point.bmp", "image/bmp")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.pointD.bmp", "image/bmp")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.pointU.bmp", "image/bmp")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.point.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.point_selected.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.point_hover.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.polyline.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.polyline_selected.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.polyline_hover.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.polygon.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.polygon_selected.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.polygon_hover.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.clearInput.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.clearInput_selected.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.clearInput_hover.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.selectFeature.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.selectFeature_selected.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.selectFeature_hover.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.selectTaskResult.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.selectTaskResult_selected.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.selectTaskResult_hover.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.preview.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.contextMenuRemove.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.contextMenuZoomTo.gif", "image/gif")] [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.images.contextMenuViewTable.gif", "image/gif")] // Embedded JavaScript [assembly: System.Web.UI.WebResource("FindNearTask_CSharp.Resources.javascript.FindNearTask.js", "text/javascript")] namespace FindNearTask_CSharp { [ System.ComponentModel.DefaultProperty("TabularResultOptions"), System.Drawing.ToolboxBitmap(typeof(FindNearTask_CSharp.FindNearTask)), System.Web.UI.ToolboxData(@"<{0}:FindNearTask runat=""server"" Width=""400px"" BackColor=""White"" BorderColor=""#999999"" BorderStyle=""Solid"" BorderWidth=""1px"" Font-Names=""Verdana"" Font-Size=""8pt"" ForeColor=""Black"" TitleBarColor=""#2F5675"" TitleBarHeight=""24px"" TitleBarSeparatorLine=""True"" Transparency=""0"" Font-Bold=""True"" TitleBarForeColor=""White"" Visible=""False"" DockingContainerElementID=""LeftPanelCellDiv"" ShowDockedContextMenu=""True"" GeometryServiceUrl=""http://tasks.arcgisonline.com/arcgis/services/Geometry/GeometryServer"" ShowDockButton=""True"" Docked=""False"" > </{0}:FindNearTask>") ] // Task that allows searching for features within a specified distance of user-drawn graphics, selected // features, or task results public class FindNearTask : ESRI.ArcGIS.ADF.Web.UI.WebControls.FloatingPanelTask { #region Instance Varables // UI Controls private ESRI.ArcGIS.ADF.Web.UI.WebControls.Toolbar _taskToolbar; private System.Web.UI.WebControls.DropDownList _selectionLayerDropDownList; private System.Web.UI.WebControls.Label _selectionLayerLabel; private System.Web.UI.WebControls.TextBox _searchDistanceTextBox; private System.Web.UI.WebControls.DropDownList _unitsDropDownList; private System.Web.UI.WebControls.DropDownList _searchLayerDropDownList; private System.Web.UI.HtmlControls.HtmlGenericControl _activityIndicatorDiv; private System.Web.UI.HtmlControls.HtmlInputButton _findButton; private ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenu _graphicsLayerContextMenu; // Tracking variables shared internally private string _taskFrameworkJobID = null; private bool _newTaskResultsPanel = false; private string _originalDataSetName = null; // Internal references to buddied Map and TaskResults controls ESRI.ArcGIS.ADF.Web.UI.WebControls.Map _map = null; ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults _taskResults = null; #endregion #region Properties #region Internal Properties // The task's input parameters. See InputParameters.cs for the parameters' class definition. internal FindNearTask_CSharp.InputParameters TaskInput { get { // Attempt to retrieve the input parameters from state InputParameters inputParameters = StateManager.GetProperty("FindNearTaskInputParameters") as InputParameters; if (inputParameters == null) { // Since no parameters were stored in state, create a new InputParameters object inputParameters = new InputParameters(); // Initialize the TaskInput property so the InputParameters object is stored in state this.TaskInput = inputParameters; } // Return the parameters return inputParameters; } set { // Store the passed-in parameters in state StateManager.SetProperty("FindNearTaskInputParameters", value); } } // Graphics resource used to store user input and buffer graphics layers. The geometries of the features // in this resource are used as input for the task. internal FindNearTask_CSharp.GraphicsResource TaskInputGraphicsResource { get { // Attempt to retrieve the task's graphics resource from state FindNearTask_CSharp.GraphicsResource taskGraphicsResource = this.StateManager.GetProperty("TaskInputGraphicsResource") as FindNearTask_CSharp.GraphicsResource; if (taskGraphicsResource == null) { // Since the task's graphics resource is not yet in state, create it and store it string resourceName = string.Format("{0} Input Graphics Resource", this.ClientID); taskGraphicsResource = new FindNearTask_CSharp.GraphicsResource(resourceName, this.MapInstance); this.StateManager.SetProperty("TaskInputGraphicsResource", taskGraphicsResource); } // Return the resource return taskGraphicsResource; } } #endregion #region Private Properties // Whether to define the search area by selecting a task result private bool SearchAreaByTaskResult { get { // Check whether the property is stored in state. If not, return false. If so, return // the value from state. if (StateManager.GetProperty("SearchAreaByTaskResult") == null) return false; else return (bool)StateManager.GetProperty("SearchAreaByTaskResult"); } set { // Store the passed-in value in state StateManager.SetProperty("SearchAreaByTaskResult", value); } } // Returns the buddied Map private ESRI.ArcGIS.ADF.Web.UI.WebControls.Map MapInstance { get { return this.TaskResultsInstance.MapInstance; } } // Returns the first buddied TaskResults container that has a buddied Map private ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults TaskResultsInstance { get { // Check whether the internal task results variable is null if (_taskResults == null) { // Iterate through the the task's buddied TaskResults containers. Exit the loop when the first one wtih // a buddied Map control is found. for (int i = 0; i < this.TaskResultsContainers.Count; i++) { _taskResults = ESRI.ArcGIS.ADF.Web.UI.WebControls.Utility.FindControl( this.TaskResultsContainers[i].Name, this.Page) as ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults; if (_taskResults != null && _taskResults.MapInstance != null) break; } } // Return the internal variable storing the reference to the TaskResults return _taskResults; } } // Counts the number of times the task has executed. Used to apply a unique ID to new TaskResultsPanels displaying resutls. private int SearchCount { get { if (this.StateManager.GetProperty("OperationCount") == null) return 1; else return (int)this.StateManager.GetProperty("OperationCount"); } set { this.StateManager.SetProperty("OperationCount", value); } } #endregion #region Public Properties /// <summary> /// How tabular results will be displayed /// </summary> [System.Web.UI.PersistenceMode(System.Web.UI.PersistenceMode.Attribute)] [System.ComponentModel.Browsable(true)] [System.ComponentModel.NotifyParentProperty(true)] [System.ComponentModel.DefaultValue(TabularResultOptions.TableInFloatingPanel)] [System.ComponentModel.Description("How tabular results will be displayed")] [System.ComponentModel.Category("Task")] public TabularResultOptions TabularResultOptions { get { // Attempt retrieving the tabular result options from state. If not found, return the default // option. Otherwise, return the value from state. object obj = StateManager.GetProperty("TabularResultOptions"); return (obj == null) ? TabularResultOptions.TableInFloatingPanel : (TabularResultOptions)obj; } // Store the passed-in value in state set { StateManager.SetProperty("TabularResultOptions", value); } } /// <summary> /// The URL of an ArcGIS Server Geometry Service. Required for calculating the search area. /// </summary> [System.Web.UI.PersistenceMode(System.Web.UI.PersistenceMode.Attribute)] [System.ComponentModel.Browsable(true)] [System.ComponentModel.NotifyParentProperty(true)] [System.ComponentModel.DefaultValue("http://tasks.arcgisonline.com/arcgis/services/Geometry/GeometryServer")] [System.ComponentModel.Description("URL for an ArcGIS Server geometry service")] [System.ComponentModel.Category("Task")] public string GeometryServiceUrl { get { // Attempt retrieving the geometry service URL from state. If not found, return the default // URL. Otherwise, return the value from state. object obj = StateManager.GetProperty("GeometryServiceUrl"); return (obj == null) ? "http://tasks.arcgisonline.com/arcgis/services/Geometry/GeometryServer" : (string)obj; } // Store the passed-in value in state set { StateManager.SetProperty("GeometryServiceUrl", value); } } #endregion #endregion #region ASP.NET WebControl Life Cycle Event Handlers protected override void CreateChildControls() { base.CreateChildControls(); // Do not create child controls if the control is being rendered at design-time if (this.DesignMode) return; // Table to format the task interface and add it to the task's controls System.Web.UI.WebControls.Table taskInterfaceTable = new System.Web.UI.WebControls.Table(); Controls.Add(taskInterfaceTable); // Row for the distance label, distance textbox, and units label System.Web.UI.WebControls.TableRow tableRow = new System.Web.UI.WebControls.TableRow(); taskInterfaceTable.Rows.Add(tableRow); // Cell for the search area tools label System.Web.UI.WebControls.TableCell tableCell = new System.Web.UI.WebControls.TableCell(); tableCell.ColumnSpan = 2; tableCell.Style[System.Web.UI.HtmlTextWriterStyle.WhiteSpace] = "nowrap"; tableRow.Cells.Add(tableCell); // Create the search area tools label and add it to the container cell System.Web.UI.WebControls.Label label = new System.Web.UI.WebControls.Label(); label.Text = "Search Area Definition Tools"; tableCell.Controls.Add(label); // Create the toolbar containing the task's tools and add it to the interface table CreateTaskToolbar(); tableCell.Controls.Add(_taskToolbar); // Table row and cell for the selection layer controls tableRow = new System.Web.UI.WebControls.TableRow(); taskInterfaceTable.Rows.Add(tableRow); tableCell = new System.Web.UI.WebControls.TableCell(); tableCell.ColumnSpan = 2; tableCell.Style[System.Web.UI.HtmlTextWriterStyle.WhiteSpace] = "nowrap"; tableRow.Cells.Add(tableCell); // Create selection layer label and drop-down list and add them to the table CreateSelectionLayerControls(); tableCell.Controls.Add(_selectionLayerLabel); tableCell.Controls.Add(_selectionLayerDropDownList); // Table row and cell for the Add New Search Areas to Previous checkbox tableRow = new System.Web.UI.WebControls.TableRow(); taskInterfaceTable.Rows.Add(tableRow); tableCell = new System.Web.UI.WebControls.TableCell(); tableCell.ColumnSpan = 2; tableCell.Style[System.Web.UI.HtmlTextWriterStyle.WhiteSpace] = "nowrap"; tableRow.Cells.Add(tableCell); // Create a checkbox to give user the option of overwriting or adding to task input geometries and add // it to the UI table tableCell.Controls.Add(CreateAddToInputCheckbox()); // Row for the search distance controls tableRow = new System.Web.UI.WebControls.TableRow(); tableRow.Style[System.Web.UI.HtmlTextWriterStyle.WhiteSpace] = "nowrap"; taskInterfaceTable.Rows.Add(tableRow); // Cell for the search distance label and textbox tableCell = new System.Web.UI.WebControls.TableCell(); tableCell.Style[System.Web.UI.HtmlTextWriterStyle.WhiteSpace] = "nowrap"; tableRow.Cells.Add(tableCell); // Create the search distance label and add it to the cell tableCell.Controls.Add(CreateSearchDistanceLabel()); // Add the search distance textbox to the table CreateSearchDistanceControls(); tableCell.Controls.Add(_searchDistanceTextBox); // Cell for the units drop-down list tableCell = new System.Web.UI.WebControls.TableCell(); tableCell.Style[System.Web.UI.HtmlTextWriterStyle.WhiteSpace] = "nowrap"; tableRow.Cells.Add(tableCell); // Add the units drop-down list to the table tableCell.Controls.Add(_unitsDropDownList); // Table row and cell for the search layer label and drop-down list tableRow = new System.Web.UI.WebControls.TableRow(); taskInterfaceTable.Rows.Add(tableRow); tableCell = new System.Web.UI.WebControls.TableCell(); tableCell.ColumnSpan = 2; tableCell.Style[System.Web.UI.HtmlTextWriterStyle.WhiteSpace] = "nowrap"; tableRow.Cells.Add(tableCell); // Create search layer label and add it to the table tableCell.Controls.Add(CreateSearchLayerLabel()); // Create selection layer drop-down list and add it to the table CreateSearchLayerDropDownList(); tableCell.Controls.Add(_searchLayerDropDownList); // Row and cell for the Find button tableRow = new System.Web.UI.WebControls.TableRow(); taskInterfaceTable.Rows.Add(tableRow); tableCell = new System.Web.UI.WebControls.TableCell(); tableCell.ColumnSpan = 2; tableCell.Style[System.Web.UI.HtmlTextWriterStyle.WhiteSpace] = "nowrap"; tableRow.Cells.Add(tableCell); // Create the Find button to the container table cell CreateFindButton(); tableCell.Controls.Add(_findButton); // Create and add the activity indicator div to the table CreateActivityIndicatorDiv(); tableCell.Controls.Add(_activityIndicatorDiv); // If tabular results are to appear in a floating panel, call the function to create the task results // context menu containing an item to show the panel if (TabularResultOptions == TabularResultOptions.TableInFloatingPanel) this.CreateTaskResultsPanelContextMenu(); // Add handlers for the task results container's node events. The NodeAdded and NodeRemoved hanlders // manage creating and destroying TaskResultsPanels for the associated task results, while the NodeClicked // handler incorporates adding the clicked task result's search geometry if the tool to specify // input by task result is selected this.TaskResultsInstance.NodeAdded += new ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNodeAddedEventHandler(TaskResults_NodeAdded); this.TaskResultsInstance.NodeRemoved += new ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNodeRemovedEventHandler(TaskResults_NodeRemoved); this.TaskResultsInstance.NodeClicked += new ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNodeClickedEventHandler(TaskResults_NodeClicked); } protected override void Render(System.Web.UI.HtmlTextWriter writer) { base.Render(writer); if (DesignMode) return; // Register the JavaScript file containing the functions used by the task if (!this.Page.ClientScript.IsStartupScriptRegistered("FindNearTaskScript")) this.Page.ClientScript.RegisterStartupScript(typeof(FindNearTask_CSharp.FindNearTask), "FindNearTaskScript", FindNearTask_CSharp.ResourceUtility.GetJavascript(this, "FindNearTask.js", typeof(FindNearTask_CSharp.FindNearTask))); // Registered the TaskResultsPanel's scripts FindNearTask_CSharp.TaskResultsPanel.RegisterScripts(this); // Find all the toolbars on the page and construct a string containing their IDs System.Collections.Generic.List<ESRI.ArcGIS.ADF.Web.UI.WebControls.Toolbar> toolbarList = ESRI.ArcGIS.ADF.Web.UI.WebControls.Utility.FindControls< ESRI.ArcGIS.ADF.Web.UI.WebControls.Toolbar>(this.Page.Controls); string toolbarIDs = ""; foreach (ESRI.ArcGIS.ADF.Web.UI.WebControls.Toolbar toolbar in toolbarList) toolbarIDs += toolbar.ClientID + ","; if (toolbarIDs.Length > 0) toolbarIDs = toolbarIDs.Substring(0, toolbarIDs.Length - 1); // Construct JavaScript to pass server-side task initialization data to the client string initializationScriptKey = "FindNearTaskInitializationScript"; if (!Page.ClientScript.IsStartupScriptRegistered(initializationScriptKey)) { string initializationScript = @" function findNearTaskInit() {{ _callbackFunctionString = ""{0}""; var toolbarIDs = '{1}'; toolbarIDs = toolbarIDs.split(','); for (var i = 0; i < toolbarIDs.length; i++) {{ var toolbar = $find(toolbarIDs[i]); if (toolbar) toolbar.add_onToolSelected(toolSelected); }} _selectionLayerLabel = $get('{2}'); _selectionLayerDropDownList = $get('{3}'); _searchDistanceTextBox = $get('{4}'); _unitsDropDownList = $get('{5}'); _buddyMapID = '{6}'; _findButton = $get('{7}'); _activityIndicatorDiv = $get('{8}'); _buddyTaskResultsID = '{9}'; initAsyncRequestHandler(); }} Sys.Application.add_init(findNearTaskInit);"; initializationScript = string.Format(initializationScript, this.CallbackFunctionString, toolbarIDs, _selectionLayerLabel.ClientID, _selectionLayerDropDownList.ClientID, _searchDistanceTextBox.ClientID, _unitsDropDownList.ClientID, this.MapInstance.ClientID, _findButton.ClientID, _activityIndicatorDiv.ClientID, this.TaskResultsInstance.ClientID); // Register the script on the page Page.ClientScript.RegisterStartupScript(this.GetType(), initializationScriptKey, initializationScript, true); } this.TaskResultsInstance.ShowRowCount = false; } #endregion #region Web ADF Control Event Handlers // Fires when a node is removed from the TaskResults control buddied to the task. If the removed node corresponds // to a TaskResultsPanel, then that panel is detroyed here. void TaskResults_NodeRemoved(object sender, ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNodeRemovedEventArgs args) { // Check whether results are being shown in a TaskResultsPanel if (this.TabularResultOptions == TabularResultOptions.TableInFloatingPanel) { // Call method to retrieve a GraphicsLayerNode that is the child of the current node. Note this method // will also check whether the current node is a GraphicsLayerNode ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode graphicsLayerNode = this.FindChildGraphicsLayerNode(args.Node); // Check whether a GraphicsLayerNode was found if (graphicsLayerNode != null) { // Construct JavaScript to find the TaskResultsPanel corresponding to the GraphicsLayerNode and // destroy it. string taskResultsPanelClientID = string.Format("{0}_{1}_TaskResultsPanel", this.ClientID, graphicsLayerNode.NodeID); string disposeResultsPanelJavaScript = @" var taskResultsPanel = $find('{0}'); if (taskResultsPanel) {{ taskResultsPanel.hide(false); taskResultsPanel.dispose(); }} var element = $get('{0}'); if (element) element.parentNode.removeChild(element);"; disposeResultsPanelJavaScript = string.Format(disposeResultsPanelJavaScript, taskResultsPanelClientID); // Encapsulate the JavaScript in a callback result and add it to the task's collection of CallbackResults ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult disposeResultsPanelCallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(disposeResultsPanelJavaScript); this.CallbackResults.Add(disposeResultsPanelCallbackResult); } } // Retrieve any FeatureNodes that are children of the removed node. Note this call will also check whether // the current node is a FeatureNode. System.Collections.Generic.List<ESRI.ArcGIS.ADF.Web.UI.WebControls.FeatureNode> featureNodes = new System.Collections.Generic.List<ESRI.ArcGIS.ADF.Web.UI.WebControls.FeatureNode>(); this.FindChildFeatureNodes(args.Node, ref featureNodes); // Check whether any FeatureNodes were found if (featureNodes.Count > 0) { // For each FeatureNode, construct JavaScript to reset the corresponding entry in the client-side array // storing FeatureNode IDs to null string removeNodeIDsJavaScript = ""; foreach (ESRI.ArcGIS.ADF.Web.UI.WebControls.FeatureNode featureNode in featureNodes) removeNodeIDsJavaScript += string.Format("_featureNodeIDs['{0}'] = null;", featureNode.NodeID); // Wrap the JavaScript in a CallbackResult and add it to the task's collection ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult removeNodeIDsCallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(removeNodeIDsJavaScript); this.CallbackResults.Add(removeNodeIDsCallbackResult); } // Add any CallbackResults created by the task to the calling controls results so they are processed on the client this.CopyCallbackResultsToCaller(this.CallbackResults); } // Fires when a node is added to the TaskResults control buddied to the Task. void TaskResults_NodeAdded(object sender, ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNodeEventArgs args) { // Check whether the internal flag indicating that a new TaskResultsPanel needs to be created is true and // results are to be shown in a TaskResultsPanel if (this._newTaskResultsPanel && (this.TabularResultOptions == TabularResultOptions.TableInFloatingPanel)) { // Get the GraphicsLayerNode that is an ancestor or descendant of the current node ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode graphicsLayerNode = this.GetRelatedGraphicsLayerNode(args.Node); // Make sure a GraphicsLayerNode was found and that the name of the dataset containing the GraphicsLayer it // references does not match the dataset name that was assigned in ExecuteTask. We do this because the Web // ADF replaces the original node with one that has IDs that are used internally by other ADF components. // The DataSetName in particular holds the name of the resource that contains the results GraphicsLayer. if (graphicsLayerNode != null && graphicsLayerNode.Layer.DataSet.DataSetName != this._originalDataSetName) { // Create the TaskResultsPanel that will be used to display results string taskResultsPanelID = string.Format("{0}_TaskResultsPanel", graphicsLayerNode.NodeID); string taskResultsPanelTitle = string.Format("{0} Results - {1}", this.Title, graphicsLayerNode.Layer.TableName); FindNearTask_CSharp.TaskResultsPanel taskResultsPanel = this.CreateTaskResultsPanel(taskResultsPanelID, taskResultsPanelTitle); // When a Web ADF FloatingPanel is rendered during an asynchronous request, the ADF automatically creates // a callback result that includes a call to the private client-side function _checkDock. In cases where the // FloatingPanel does not have a docking container, this interferes with the FloatingPanel's initialization. // So we remove that callback result here. string checkDockJavaScript = string.Format("$find('{0}')._checkDock();", taskResultsPanel.ClientID); ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult callbackResultToRemove = null; foreach (ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult callbackResult in taskResultsPanel.CallbackResults) { if (callbackResult.Parameters[0] as string == checkDockJavaScript) { callbackResultToRemove = callbackResult; break; } } if (callbackResultToRemove != null) taskResultsPanel.CallbackResults.Remove(callbackResultToRemove); // Get the name of the resource containing the results GraphicsLayer and call SetLayer to associate the // TaskResultsPanel with the GraphicsLayer string resourceName = graphicsLayerNode.Layer.DataSet.DataSetName; taskResultsPanel.SetLayer(graphicsLayerNode.Layer as ESRI.ArcGIS.ADF.Web.Display.Graphics.FeatureGraphicsLayer, resourceName, this.TaskResultsInstance.Map); // Call ShowFloatingPanel to display the results panel taskResultsPanel.ShowFloatingPanel(); // Copy the results panel's callback results to the task's results collection so changes made to the // panel requiring client-side handling are processed this.CallbackResults.CopyFrom(taskResultsPanel.CallbackResults); // Reset the flag indicating whether a new TaskResultsPanel needs to be created this._newTaskResultsPanel = false; } } // Find any FeatureNodes that are descendants of the added node System.Collections.Generic.List<ESRI.ArcGIS.ADF.Web.UI.WebControls.FeatureNode> featureNodes = new System.Collections.Generic.List<ESRI.ArcGIS.ADF.Web.UI.WebControls.FeatureNode>(); this.FindChildFeatureNodes(args.Node, ref featureNodes); // Check whether any FeatureNodes were found if (featureNodes.Count > 0) { // Create JavaScript to add each FeatureNode's ID to a client-side array. This allows the tool to // specify search area by clicking on a task result to determine if a clicked node is a FeatureNode // and show a progress indicator accordingly. string defineNodeIDsJavaScript = ""; foreach (ESRI.ArcGIS.ADF.Web.UI.WebControls.FeatureNode featureNode in featureNodes) defineNodeIDsJavaScript += string.Format("_featureNodeIDs['{0}'] = true;", featureNode.NodeID); // Put the JavaScript in a CallbackResult and add it to the task's collection ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult defineNodeIDsCallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(defineNodeIDsJavaScript); this.CallbackResults.Add(defineNodeIDsCallbackResult); } // Check whether the control that initiated the asynchronous request is the task. If not, copy the task's // callback results to the control that did. if (this.GetCallingControl(this.Page).UniqueID != this.UniqueID) this.CopyCallbackResultsToCaller(this.CallbackResults); } // Fires when a node on the buddied TaskResults control is clicked. Updates the search area geometry with that of // the feature corresponding to the clicked node if the node is a FeatureNode and the tool to specify search area by // task result is active, void TaskResults_NodeClicked(object sender, ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNodeEventArgs args) { // Check whether the passed-in node is a feature node and the define search area by task result tool is active if (this.SearchAreaByTaskResult && (args.Node is ESRI.ArcGIS.ADF.Web.UI.WebControls.FeatureNode)) { // Get a reference to the clicked node as a FeatureNode ESRI.ArcGIS.ADF.Web.UI.WebControls.FeatureNode clickedFeatureNode = args.Node as ESRI.ArcGIS.ADF.Web.UI.WebControls.FeatureNode; // Loop through the data of the FeatureNode until the feature geometry is found foreach (object value in clickedFeatureNode.DataRow.ItemArray) { if (value is ESRI.ArcGIS.ADF.Web.Geometry.Geometry) { // Put the feature geometry in a geometry array ESRI.ArcGIS.ADF.Web.Geometry.Geometry[] inputGeometries = new ESRI.ArcGIS.ADF.Web.Geometry.Geometry[1]; inputGeometries[0] = value as ESRI.ArcGIS.ADF.Web.Geometry.Geometry; // Update the task's input geometries with the feature geometry this.TaskInput.SetUserInputGeometries(inputGeometries); // Update the task's user input and buffer graphics layer this.UpdateInputGraphicsLayers(); // Create a callback result to call the client-side function that hides the activity indicator string hideActivityIndicatorJavaScript = "hideUpdateAreaIndicator();"; ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult hideIndicatorCallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(hideActivityIndicatorJavaScript); this.CallbackResults.Add(hideIndicatorCallbackResult); // Check whether the task initiated the request. If not, copy the callback results to the initiating // control so the updates to the GraphicsLayer are processed on the client. if (this.GetCallingControl(this.Page).UniqueID != this.UniqueID) this.CopyCallbackResultsToCaller(this.CallbackResults); break; } } } } // Fires when the custom GraphicLayer context menu is closed. private void GraphicsLayerContextMenu_Dismissed(object sender, ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuDismissedEventArgs args) { this.TaskResultsInstance.ContextMenuDismissed(_graphicsLayerContextMenu, args); } // Fires when an item on the custom GraphicsLayer context menu is clicked private void GraphicsLayerContextMenu_ItemClicked(object sender, ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItemEventArgs args) { // Get the node on which the context menu was displayed ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode graphicsLayerNode = TaskResultsInstance.Nodes.FindByNodeID(args.Context) as ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode; // Check the text of the item clicked switch (args.Item.Text) { case "Zoom To Selected Features": if (graphicsLayerNode == null || this.MapInstance == null) return; bool hasFeaturesSelected = false; // Get the GraphicsLayer associated with the node ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsLayer graphicsLayer = graphicsLayerNode.Layer; // Declare an envelope to store the combined extent of all features in the layer ESRI.ArcGIS.ADF.Web.Geometry.Envelope adfEnvelope = new ESRI.ArcGIS.ADF.Web.Geometry.Envelope(); // Loop through the rows (i.e. features) of the graphics layer, adding the envelope of each to the // combined extent envelope for (int i = 0; i < graphicsLayer.Rows.Count; i++) { if ((bool)graphicsLayer.Rows[i][graphicsLayer.IsSelectedColumn]) { hasFeaturesSelected = true; ESRI.ArcGIS.ADF.Web.Geometry.Geometry rowGeometry = graphicsLayer.GeometryFromRow(graphicsLayer.Rows[i]); adfEnvelope.Union(rowGeometry); } } if (!hasFeaturesSelected) return; // If combined envelope width or height is zero, zoom in the amount specified by the // ZoomToPointFactor property if (adfEnvelope.Width == 0 || adfEnvelope.Height == 0) { ESRI.ArcGIS.ADF.Web.Geometry.Point adfPoint = new ESRI.ArcGIS.ADF.Web.Geometry.Point(adfEnvelope.XMax, adfEnvelope.YMax); ESRI.ArcGIS.ADF.Web.Geometry.Envelope fullExtentEnvelope = this.MapInstance.GetFullExtent(); double widthMargin = (fullExtentEnvelope.Width / TaskResultsInstance.ZoomToPointFactor) / 2; double heightMargin = (fullExtentEnvelope.Height / TaskResultsInstance.ZoomToPointFactor) / 2; ESRI.ArcGIS.ADF.Web.Geometry.Envelope zoomToEnvelope = new ESRI.ArcGIS.ADF.Web.Geometry.Envelope(); zoomToEnvelope.XMax = adfPoint.X + widthMargin; zoomToEnvelope.XMin = adfPoint.X - widthMargin; zoomToEnvelope.YMax = adfPoint.Y + heightMargin; zoomToEnvelope.YMin = adfPoint.Y - heightMargin; this.MapInstance.Extent = zoomToEnvelope; } else { // Apply the combined feature extent to the map this.MapInstance.Extent = adfEnvelope; } // Copy the map's callback results to the context menu so the extent change is processed on the client _graphicsLayerContextMenu.CallbackResults.CopyFrom(this.MapInstance.CallbackResults); break; case "Remove": if (this.MapInstance == null || graphicsLayerNode == null) return; // Check whether there is a GraphicsLayer associated with the node if (graphicsLayerNode.Layer != null) { // Remove the GraphicsLayer associated with the node from the map and refresh the layer's // parent resource string graphicsResourceName = graphicsLayerNode.RemoveFromMap(this.TaskResultsInstance); this.MapInstance.RefreshResource(graphicsResourceName); // Copy the map's callback results to the context menu so the map is updated on the client _graphicsLayerContextMenu.CallbackResults.CopyFrom(this.MapInstance.CallbackResults); } // Remove the node and refresh the buddied TaskResults control graphicsLayerNode.Remove(); this.TaskResultsInstance.Refresh(); // Copy the buddied TaskResults control's callback results to the context menu so the node removal // is processed on the client _graphicsLayerContextMenu.CallbackResults.CopyFrom(TaskResultsInstance.CallbackResults); break; case "View Attribute Table": // Construct JavaScript to call the client-side Web ADF function to display the TaskResultsPanel string taskResultsPanelClientID = string.Format("{0}_{1}_TaskResultsPanel", this.ClientID, args.Context); string showTaskResultsPanelJavaScript =string.Format("showFloatingPanel('{0}', false);", taskResultsPanelClientID); ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult showTaskResultsPanelCallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(showTaskResultsPanelJavaScript); _graphicsLayerContextMenu.CallbackResults.Add(showTaskResultsPanelCallbackResult); break; } } #endregion #region ICallbackEventHandler Overrides - GetCallbackResults public override string GetCallbackResult() { // Convert the callback argument string into a name-value collection using the Web ADF's callback // argument parsing utility System.Collections.Specialized.NameValueCollection callbackArgsCollection = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection( this.CallbackEventArgument); // Get the task's job ID _taskFrameworkJobID = callbackArgsCollection["taskJobID"]; // Get the callback event argument string eventArg = callbackArgsCollection["EventArg"]; switch (eventArg) { // Check whether the event argument indicates that the user has modified the search distance case "updateSearchArea": // Get the updated search distance and make sure it is valid string searchDistance = callbackArgsCollection["searchDistance"]; string units = callbackArgsCollection["units"]; // Make sure a search distance was entered if (!string.IsNullOrEmpty(searchDistance)) { float newSearchDistance; if (float.TryParse(searchDistance, out newSearchDistance)) this.TaskInput.SearchDistance = newSearchDistance; this.TaskInput.Units = units; // Update the graphics layer showing the search area this.UpdateInputGraphicsLayers(); // Copy the callback results from the map so the graphics layer update is processed // on the client this.CallbackResults.CopyFrom(MapInstance.CallbackResults); } // Create callback result to hide the task's activity indicator ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult hideActivityIndicatorCallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript("hideUpdateAreaIndicator();"); this.CallbackResults.Add(hideActivityIndicatorCallbackResult); break; case "toggleSelectByTaskResult": // Set the flag indicating wheteher the define search area by task result tool this.SearchAreaByTaskResult = bool.Parse(callbackArgsCollection["Value"]); break; case "toggleAddToInput": // Set the flag indicating whether newly defined geometries are to be added to those already defined this.TaskInput.AddToInputGeometry = !this.TaskInput.AddToInputGeometry; break; case "updateSearchLayer": // Get the map resource and layer ID for the layer clicked. These values are stored as the value of // the tree view plus node and are comma delimited. string[] searchLayerParameters = callbackArgsCollection["searchLayerParameters"].Split(new char[] { ',' }); // Update the task's input parameters with the node's information this.TaskInput.SearchResource = searchLayerParameters[0]; this.TaskInput.SearchLayer = searchLayerParameters[1]; break; } return base.GetCallbackResult(); } // Updates the geometries of the user input and buffer graphics layers internal void UpdateInputGraphicsLayers() { // If there are not defined input geometries, exit the function if (this.TaskInput.UserInputGeometries == null || this.TaskInput.UserInputGeometries.Length == 0) return; // Get the graphics layer displaying the user defined geometries and clear it ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer inputGraphicsLayer = this.TaskInputGraphicsResource.GetUserInputLayer(this.MapInstance.MapResourceManagerInstance) as ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer; ESRI.ArcGIS.ADF.Web.Geometry.Geometry[] adfSearchGeometries = this.TaskInput.UserInputGeometries; inputGraphicsLayer.Clear(); // Get the search distance float searchDistance = TaskInput.SearchDistance; // Make sure the user specified geometries and distance are valid if (adfSearchGeometries != null && !float.IsNaN(searchDistance) && searchDistance > 0.0) { ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicElement inputGraphicElement = null; // Create a symbol for the user specified geometry for (int i = 0; i < adfSearchGeometries.Length; i++) { if (adfSearchGeometries[i] is ESRI.ArcGIS.ADF.Web.Geometry.Point) { ESRI.ArcGIS.ADF.Web.Display.Symbol.SimpleMarkerSymbol adfSearchPointSymbol = new ESRI.ArcGIS.ADF.Web.Display.Symbol.SimpleMarkerSymbol( System.Drawing.Color.Green, 10, ESRI.ArcGIS.ADF.Web.Display.Symbol.MarkerSymbolType.Star); // Create a graphic element for the search point and add it to the graphics layer inputGraphicElement = new ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicElement(adfSearchGeometries[i], adfSearchPointSymbol); } else if (adfSearchGeometries[i] is ESRI.ArcGIS.ADF.Web.Geometry.Polyline) { ESRI.ArcGIS.ADF.Web.Display.Symbol.SimpleLineSymbol adfSearchLineSymbol = new ESRI.ArcGIS.ADF.Web.Display.Symbol.SimpleLineSymbol(System.Drawing.Color.Green, 4, ESRI.ArcGIS.ADF.Web.Display.Symbol.LineType.Solid); inputGraphicElement = new ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicElement(adfSearchGeometries[i], adfSearchLineSymbol); } else if (adfSearchGeometries[i] is ESRI.ArcGIS.ADF.Web.Geometry.Polygon) { ESRI.ArcGIS.ADF.Web.Display.Symbol.SimpleFillSymbol adfSearchFillSymbol = new ESRI.ArcGIS.ADF.Web.Display.Symbol.SimpleFillSymbol(System.Drawing.Color.Green, System.Drawing.Color.Black, 50, 20, ESRI.ArcGIS.ADF.Web.Display.Symbol.PolygonFillType.Solid); inputGraphicElement = new ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicElement(adfSearchGeometries[i], adfSearchFillSymbol); } inputGraphicsLayer.Add(inputGraphicElement); } // Get the buffer geometry for the search geometry and distance this.TaskInput.BufferGeometry = this.BufferGeometries(adfSearchGeometries, searchDistance, this.TaskInput.Units); // Create a graphic element for the buffer and add it to the graphics layer ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicElement bufferElement = new ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicElement(this.TaskInput.BufferGeometry, System.Drawing.Color.Red, 75); ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer bufferGraphicsLayer = this.TaskInputGraphicsResource.GetBufferLayer(this.MapInstance.MapResourceManagerInstance); bufferGraphicsLayer.Clear(); bufferGraphicsLayer.Add(bufferElement); } // Refresh the resource containing the input graphics layer MapInstance.RefreshResource(this.TaskInputGraphicsResource.ResourceName); // Check whether the map is the control that initiated the request. If not, copy the Map's callback results to the // initiating control so the map's updates are processed on the client. if (this.GetCallingControl(this.Page).UniqueID != this.MapInstance.UniqueID) this.CopyCallbackResultsToCaller(this.MapInstance.CallbackResults); } // Clears the user input and buffer graphics layers internal void ClearTaskInput() { // Temporarily store AddToInputGeometry bool addToInputGeometry = this.TaskInput.AddToInputGeometry; // Set AddToInputGeometry to false and pass null to SetUserInputGeometries to clear the input // geometries this.TaskInput.AddToInputGeometry = false; this.TaskInput.SetUserInputGeometries(null); // Revert the value of AddToInputGeometry this.TaskInput.AddToInputGeometry = addToInputGeometry; // Set the buffer geometry to null this.TaskInput.BufferGeometry = null; // Retrieve and clear the user input and buffer graphics layers ESRI.ArcGIS.ADF.Web.Display.Graphics.ElementGraphicsLayer elementGraphicsLayer = this.TaskInputGraphicsResource.GetUserInputLayer(this.MapInstance.MapResourceManagerInstance); elementGraphicsLayer.Clear(); elementGraphicsLayer = this.TaskInputGraphicsResource.GetBufferLayer( this.MapInstance.MapResourceManagerInstance); elementGraphicsLayer.Clear(); // Update the resource containing the input graphics layers this.MapInstance.RefreshResource(this.TaskInputGraphicsResource.ResourceName); } #endregion #region Web ADF Task Overrides - ExecuteTask, GetGISResourceItemDependencies // Called when the Find button is clicked public override void ExecuteTask() { if (this.TaskInput.BufferGeometry == null) return; // Get the buddied map resource manager ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceManager mapResourceManager = this.MapInstance.MapResourceManagerInstance; // Get the map resource item containing the resource to be searched ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceItem mapResourceItem = mapResourceManager.ResourceItems.Find(this.TaskInput.SearchResource); // Make sure the search resource is initialized if (mapResourceItem.Resource == null || !mapResourceItem.Resource.Initialized) mapResourceItem.InitializeResource(); // Get a reference to the resource item's map resource ESRI.ArcGIS.ADF.Web.DataSources.IMapResource commonMapResource = mapResourceItem.Resource as ESRI.ArcGIS.ADF.Web.DataSources.IMapResource; // Use the resource to create a query functionality string queryFunctionalityName = string.Format("{0}_QueryFunctionality", this.ID); ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality queryFunctionality = commonMapResource.CreateFunctionality(typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), queryFunctionalityName) as ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality; // Instantiate a spatial filter with the buffer geometry ESRI.ArcGIS.ADF.Web.SpatialFilter adfSpatialFilter = new ESRI.ArcGIS.ADF.Web.SpatialFilter(); adfSpatialFilter.Geometry = this.TaskInput.BufferGeometry; // Specify that the query return the geometries of result features adfSpatialFilter.ReturnADFGeometries = true; // Set the spatial reference of the query results to match that of the map adfSpatialFilter.OutputSpatialReference = MapInstance.SpatialReference; // Execute the query System.Data.DataTable resultsDataTable = queryFunctionality.Query(null, TaskInput.SearchLayer, adfSpatialFilter); // Make sure results were found and they can be shown as a graphics layer if (resultsDataTable == null || !(resultsDataTable is ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsLayer)) return; // Convert query results to a graphics layer ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsLayer resultsGraphicsLayer = ESRI.ArcGIS.ADF.Web.Converter.ToGraphicsLayer(resultsDataTable); // Retrieve and apply the layer format of the search layer to the results ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerFormat layerFormat = ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerFormat.FromMapResourceManager(mapResourceManager, this.TaskInput.SearchResource, this.TaskInput.SearchLayer); layerFormat.Apply(resultsGraphicsLayer); // Set RenderOnClient to true so highlighting and maptips are enabled on the results resultsGraphicsLayer.RenderOnClient = true; // Select all features so that they are visible by default foreach (System.Data.DataRow dataRow in resultsGraphicsLayer.Rows) dataRow[resultsGraphicsLayer.IsSelectedColumn] = true; // Create a graphics dataset and add the results graphics layer to it ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsDataSet resultsGraphicsDataSet = new ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsDataSet(); resultsGraphicsDataSet.DataSetName = string.Format("{0} Results ({1})", this.Title, resultsGraphicsLayer.Rows.Count); resultsGraphicsDataSet.Tables.Add(resultsGraphicsLayer); // Get the number of searches performed and append the ordinal suffix string searchCount = this.SearchCount.ToString(); string searchCountDescription; switch (searchCount.Substring(searchCount.Length - 1)) { case "1": searchCount += "st"; break; case "2": searchCount += "nd"; break; case "3": searchCount += "rd"; break; default: searchCount += "th"; break; } // Create a count description with the search count searchCountDescription = string.Format("{0} search", searchCount); // Create the results GraphicsLayer's table name from the ADF generated table name, the number of // rows, and the search count string resultsGraphicsLayer.TableName = string.Format("{0} ({1} found, {2})", resultsGraphicsLayer.TableName, resultsGraphicsLayer.Rows.Count, searchCountDescription); // increment the search count this.SearchCount++; // If the tabular results are to be formatted in a tree view in the task results container, // assign the graphics dataset to the task's results. Otherwise, call the method to create // a custom task results node and assign that method's return value as the task's results. if (TabularResultOptions == FindNearTask_CSharp.TabularResultOptions.TreeViewInTaskResults) this.Results = resultsGraphicsDataSet; else if (this.TabularResultOptions == FindNearTask_CSharp.TabularResultOptions.TableInFloatingPanel) { this.Results = this.CreateCustomTaskResultsNode(resultsGraphicsDataSet); if (resultsGraphicsLayer.Rows.Count > 0) { this._newTaskResultsPanel = true; this._originalDataSetName = resultsGraphicsDataSet.DataSetName; } } } // Used by Manager to see if task requires a particular resource item in a resource manager. Since // this task has no dependencies, the implementation here returns null. public override System.Collections.Generic.List< ESRI.ArcGIS.ADF.Web.UI.WebControls.GISResourceItemDependency> GetGISResourceItemDependencies() { return null; } #endregion #region Private Methods // Retrieves queryable layers from all resources in the passed-in MapResourceManager private void GetQueryableLayers(ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceManager mapResourceManager, out System.Collections.Generic.Dictionary<string, string[]> layerNamesByResources, out System.Collections.Generic.Dictionary<string, string[]> layerIDsByResources) { layerNamesByResources = new System.Collections.Generic.Dictionary<string, string[]>(); layerIDsByResources = new System.Collections.Generic.Dictionary<string, string[]>(); bool initializedResourceManager = false; try { // If the MapResourceManager is not initialize, do so here if (!mapResourceManager.Initialized) { mapResourceManager.Initialize(); initializedResourceManager = true; } ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceItem mapResourceItem; // Loop through the resources in the MapResourceManager for (int i = 0; i < mapResourceManager.ResourceItems.Count; i++) { mapResourceItem = mapResourceManager.ResourceItems[i]; // If the current resource is not displayed in the Toc, skip to the next if (!mapResourceItem.DisplaySettings.DisplayInTableOfContents) continue; // Ensure the resource is initialized mapResourceItem.InitializeResource(); // Get the map resource from the resource item ESRI.ArcGIS.ADF.Web.DataSources.IMapResource commonMapResource = mapResourceItem.Resource as ESRI.ArcGIS.ADF.Web.DataSources.IMapResource; if (commonMapResource == null) continue; // If the resource does not support querying, skip to the next if (!commonMapResource.SupportsFunctionality(typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality))) continue; // Create a query functoinality form the resource ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality commonQueryFunctionality = commonMapResource.CreateFunctionality( typeof(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), System.Guid.NewGuid().ToString("N")) as ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality; // Get arrays containing the resources queryable layer names and IDs string[] layerIDs = null; string[] layerNames = null; commonQueryFunctionality.GetQueryableLayers(null, out layerIDs, out layerNames); // Add the arrays to the layer names and IDs dictionaries, along with the name of the current resource item layerNamesByResources.Add(mapResourceItem.Name, layerNames); layerIDsByResources.Add(mapResourceItem.Name, layerIDs); } } catch { } finally { // If the MapResourceManager was initialized in this method, call Dispose to restore it to its initial state if (initializedResourceManager) mapResourceManager.Dispose(); } return; } #region Task Results Setup Methods // Creates a TaskResultNode customized for use with a TaskResultsPanel private ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResultNode CreateCustomTaskResultsNode( ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsDataSet graphicsDataSet) { // Instantiate a TaskResultNode ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResultNode taskResultNode = new ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResultNode(); // Set the node's text to be the name of the passed-in dataset taskResultNode.Text = graphicsDataSet.DataSetName; // Iterate through the tables in the dataset, creating a node for each for (int i = 0; i < graphicsDataSet.Tables.Count; i++) { // Check whether the current table contains data for a GraphicsLayer if (graphicsDataSet.Tables[i] is ESRI.ArcGIS.ADF.Web.Display.Graphics.GraphicsLayer) { // Create a GraphicsLayerNode with the data from the current table. Make it so the node only // contains the legend swatch. ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode graphicsLayerNode = this.TaskResultsInstance.CreateDataTableNode(graphicsDataSet.Tables[i], false, true, false, graphicsDataSet.Tables[i].TableName, graphicsDataSet.Tables[i].TableName) as ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode; // Associate a custom context menu with the node. This allows opening the associated TaskResultsPanel. this.SetupContextMenu(graphicsLayerNode); // Add the node to the buddied TaskResults control taskResultNode.Nodes.Add(graphicsLayerNode); } else { // Since the table does not represent a GraphicsLayer, create a node that includes the table's data ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode treeViewPlusNode = TaskResultsInstance.CreateDataTableNode(graphicsDataSet.Tables[i], true, true, true, graphicsDataSet.Tables[i].TableName, graphicsDataSet.Tables[i].TableName); // Add the node to the TaskResults control taskResultNode.Nodes.Add(treeViewPlusNode); } } // Call SetupTaskResultNode to initialize the functionality of the parent node TaskResultsInstance.SetupTaskResultNode(this, _taskFrameworkJobID, this.TaskInput, taskResultNode); return taskResultNode; } // Creates a TaskResultsPanel with the passed-in ID and title private FindNearTask_CSharp.TaskResultsPanel CreateTaskResultsPanel(string ID, string title) { // Initialize the TaskResultsPanel FindNearTask_CSharp.TaskResultsPanel taskResultsPanel = new FindNearTask_CSharp.TaskResultsPanel(); taskResultsPanel.ID = ID; taskResultsPanel.Visible = false; taskResultsPanel.CopyAppearance(this); taskResultsPanel.Style[System.Web.UI.HtmlTextWriterStyle.Position] = "absolute"; taskResultsPanel.Style[System.Web.UI.HtmlTextWriterStyle.Left] = "200px"; taskResultsPanel.Style[System.Web.UI.HtmlTextWriterStyle.Top] = "200px"; taskResultsPanel.ExpandCollapseButton = true; taskResultsPanel.WidthResizable = true; taskResultsPanel.HeightResizable = true; taskResultsPanel.Title = title; taskResultsPanel.Docked = false; taskResultsPanel.InitialMaxHeight = new System.Web.UI.WebControls.Unit(300, System.Web.UI.WebControls.UnitType.Pixel); taskResultsPanel.InitialMaxWidth = new System.Web.UI.WebControls.Unit(500, System.Web.UI.WebControls.UnitType.Pixel); // Add the panel to the task's controls collection this.Controls.Add(taskResultsPanel); // Since we are adding the taskResultsPanel dynamically at run time, script must be created and // returned to the client that initializes the panel client-side. InitializeOnClient creates // this script and adds it to the panel as a callback result. taskResultsPanel.InitializeOnClient(this, this.CallbackFunctionString); return taskResultsPanel; } // Instantiates and initializes the context menu to show on task results if results are being displayed in a // TaskResultsPanel. private void CreateTaskResultsPanelContextMenu() { // Instantiate and initialize the context menu _graphicsLayerContextMenu = new ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenu(); _graphicsLayerContextMenu.ID = "graphicsLayerContextMenu"; _graphicsLayerContextMenu.BorderColor = System.Drawing.Color.Silver; _graphicsLayerContextMenu.BorderStyle = System.Web.UI.WebControls.BorderStyle.Solid; _graphicsLayerContextMenu.BorderWidth = new System.Web.UI.WebControls.Unit(1, System.Web.UI.WebControls.UnitType.Pixel); _graphicsLayerContextMenu.HoverColor = System.Drawing.Color.Gainsboro; _graphicsLayerContextMenu.BackColor = System.Drawing.Color.White; _graphicsLayerContextMenu.ForeColor = ForeColor; _graphicsLayerContextMenu.Font.CopyFrom(this.Font); _graphicsLayerContextMenu.UseDefaultWebResources = this.UseDefaultWebResources; // Wire item clicked and menu dismissed event handlers _graphicsLayerContextMenu.ItemClicked += new ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItemClickedEventHandler(GraphicsLayerContextMenu_ItemClicked); _graphicsLayerContextMenu.Dismissed += new ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuDismissedEventHandler(GraphicsLayerContextMenu_Dismissed); // Add a menu item to zoom to selected features ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem contextMenuItem = new ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem(); contextMenuItem.ImageUrl = ResourceUtility.GetImage("contextMenuZoomTo.gif", this, typeof(FindNearTask)); contextMenuItem.Text = "Zoom To Selected Features"; _graphicsLayerContextMenu.Items.Add(contextMenuItem); // Add a menu item to remove the GraphicsLayer corresponding to the node on which the context menu was shown contextMenuItem = new ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem(); contextMenuItem.ImageUrl = ResourceUtility.GetImage("contextMenuRemove.gif", this, typeof(FindNearTask)); contextMenuItem.Text = "Remove"; _graphicsLayerContextMenu.Items.Add(contextMenuItem); // Add a menu item to show the corresponding TaskResultsPanel contextMenuItem = new ESRI.ArcGIS.ADF.Web.UI.WebControls.ContextMenuItem(); contextMenuItem.ImageUrl = ResourceUtility.GetImage("contextMenuViewTable.gif", this, typeof(FindNearTask)); contextMenuItem.Text = "View Attribute Table"; _graphicsLayerContextMenu.Items.Add(contextMenuItem); // Add the context menu to the task's controls collection this.Controls.Add(_graphicsLayerContextMenu); } // Method that hooks up the context menu to graphics layer node. void SetupContextMenu(ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode graphicsLayerNode) { TaskResultsInstance.SetupContextMenu(_graphicsLayerContextMenu, graphicsLayerNode); } #endregion #region User Interface Creation Methods // Instantiates and populates FindNearTask's toolbar private void CreateTaskToolbar() { // Instantiate the toolbar and add it to the cell _taskToolbar = new ESRI.ArcGIS.ADF.Web.UI.WebControls.Toolbar(); // Initialize toolbar properties _taskToolbar.UseDefaultWebResources = this.UseDefaultWebResources; _taskToolbar.ID = "FindNearTaskToolbar"; _taskToolbar.WebResourceLocation = this.WebResourceLocation; _taskToolbar.BuddyControlType = ESRI.ArcGIS.ADF.Web.UI.WebControls.BuddyControlType.Map; _taskToolbar.ToolbarStyle = ESRI.ArcGIS.ADF.Web.UI.WebControls.ToolbarStyle.ImageOnly; _taskToolbar.Height = new System.Web.UI.WebControls.Unit("32px"); _taskToolbar.Width = new System.Web.UI.WebControls.Unit("192px"); // Create the add search point tool and add it to the toolbar _taskToolbar.ToolbarItems.Add(CreateSearchPointTool()); // Create the add search polyline tool and add it to the toolbar _taskToolbar.ToolbarItems.Add(CreateSearchPolylineTool()); // Create the add search polygon tool and add it to the toolbar _taskToolbar.ToolbarItems.Add(CreateSearchPolygonTool()); // Create the select input by task results tool and add it to the toolbar _taskToolbar.ToolbarItems.Add(CreateInputByTaskResultTool()); // Create the select input by map tool and add it to the toolbar _taskToolbar.ToolbarItems.Add(CreateInputByMapTool()); // Create the clear input tool and add it to the toolbar _taskToolbar.ToolbarItems.Add(CreateClearInputCommand()); // Get the names of the toolbar groups buddied to the map string[] toolbarGroupNamesArray = ESRI.ArcGIS.ADF.Web.UI.WebControls.Toolbar.FindToolbarGroupsBuddiedTo(MapInstance.UniqueID, Page); // If the map is not buddied to any toolbar groups, create a new toolbar group for it. Otherwise, use an // existing one. if (toolbarGroupNamesArray == null || toolbarGroupNamesArray.Length < 1) _taskToolbar.Group = string.Format("{0}_FindNearTaskToolbarGroup", MapInstance.UniqueID); else _taskToolbar.Group = toolbarGroupNamesArray[0]; // Encapsulate the map in a BuddyControl and add it to the toolbar's buddy control collection ESRI.ArcGIS.ADF.Web.UI.WebControls.BuddyControl mapBuddyControl = new ESRI.ArcGIS.ADF.Web.UI.WebControls.BuddyControl(MapInstance.UniqueID); _taskToolbar.BuddyControls.Add(mapBuddyControl); } // Creates the tool to define search area by drawing a point private ESRI.ArcGIS.ADF.Web.UI.WebControls.Tool CreateSearchPointTool() { ESRI.ArcGIS.ADF.Web.UI.WebControls.Tool addSearchPointTool = new ESRI.ArcGIS.ADF.Web.UI.WebControls.Tool(); addSearchPointTool.Name = "SearchAreaByPoint"; addSearchPointTool.ServerActionAssembly = "FindNearTask_CSharp"; addSearchPointTool.ServerActionClass = "FindNearTask_CSharp.SearchAreaByPoint"; addSearchPointTool.ToolTip = "Draw a point to search near"; addSearchPointTool.ClientAction = ESRI.ArcGIS.ADF.Web.UI.WebControls.MapClientToolAction.Point.ToString(); addSearchPointTool.DefaultImage = ResourceUtility.GetImage("point.gif", this, typeof(FindNearTask)); addSearchPointTool.SelectedImage = ResourceUtility.GetImage("point_selected.gif", this, typeof(FindNearTask)); addSearchPointTool.HoverImage = ResourceUtility.GetImage("point_hover.gif", this, typeof(FindNearTask)); return addSearchPointTool; } // Creates the tool to define search area by drawing a polyline private ESRI.ArcGIS.ADF.Web.UI.WebControls.Tool CreateSearchPolylineTool() { ESRI.ArcGIS.ADF.Web.UI.WebControls.Tool addSearchPolylineTool = new ESRI.ArcGIS.ADF.Web.UI.WebControls.Tool(); addSearchPolylineTool.Name = "SearchAreaByLine"; addSearchPolylineTool.ServerActionAssembly = "FindNearTask_CSharp"; addSearchPolylineTool.ServerActionClass = "FindNearTask_CSharp.SearchAreaByPolyline"; addSearchPolylineTool.ToolTip = "Draw a polyline to search near"; addSearchPolylineTool.ClientAction = ESRI.ArcGIS.ADF.Web.UI.WebControls.MapClientToolAction.Polyline.ToString(); addSearchPolylineTool.DefaultImage = ResourceUtility.GetImage("polyline.gif", this, typeof(FindNearTask)); addSearchPolylineTool.SelectedImage = ResourceUtility.GetImage("polyline_selected.gif", this, typeof(FindNearTask)); addSearchPolylineTool.HoverImage = ResourceUtility.GetImage("polyline_hover.gif", this, typeof(FindNearTask)); return addSearchPolylineTool; } // Creates the tool to define search area by drawing a polygon private ESRI.ArcGIS.ADF.Web.UI.WebControls.Tool CreateSearchPolygonTool() { ESRI.ArcGIS.ADF.Web.UI.WebControls.Tool addSearchPolygonTool = new ESRI.ArcGIS.ADF.Web.UI.WebControls.Tool(); addSearchPolygonTool.Name = "SearchAreaByPolygon"; addSearchPolygonTool.ServerActionAssembly = "FindNearTask_CSharp"; addSearchPolygonTool.ServerActionClass = "FindNearTask_CSharp.SearchAreaByPolygon"; addSearchPolygonTool.ToolTip = "Draw a polygon to search near"; addSearchPolygonTool.ClientAction = ESRI.ArcGIS.ADF.Web.UI.WebControls.MapClientToolAction.Polygon.ToString(); addSearchPolygonTool.DefaultImage = ResourceUtility.GetImage("polygon.gif", this, typeof(FindNearTask)); addSearchPolygonTool.SelectedImage = ResourceUtility.GetImage("polygon_selected.gif", this, typeof(FindNearTask)); addSearchPolygonTool.HoverImage = ResourceUtility.GetImage("polygon_hover.gif", this, typeof(FindNearTask)); return addSearchPolygonTool; } // Creates the tool to define search area by selecting a task result private ESRI.ArcGIS.ADF.Web.UI.WebControls.Tool CreateInputByTaskResultTool() { ESRI.ArcGIS.ADF.Web.UI.WebControls.Tool selectInputByTaskResultTool = new ESRI.ArcGIS.ADF.Web.UI.WebControls.Tool(); selectInputByTaskResultTool.Name = "SearchAreaByTaskResult"; selectInputByTaskResultTool.ServerActionAssembly = "FindNearTask_CSharp"; selectInputByTaskResultTool.ServerActionClass = "FindNearTask_CSharp.SearchAreaByTaskResult"; selectInputByTaskResultTool.ToolTip = "Select a task result to search near"; selectInputByTaskResultTool.ClientAction = ESRI.ArcGIS.ADF.Web.UI.WebControls.MapClientToolAction.Point.ToString(); selectInputByTaskResultTool.DefaultImage = ResourceUtility.GetImage("selectTaskResult.gif", this, typeof(FindNearTask)); selectInputByTaskResultTool.SelectedImage = ResourceUtility.GetImage("selectTaskResult_selected.gif", this, typeof(FindNearTask)); selectInputByTaskResultTool.HoverImage = ResourceUtility.GetImage("selectTaskResult_hover.gif", this, typeof(FindNearTask)); return selectInputByTaskResultTool; } // Creates the tool to define search area by selecting features from the map private ESRI.ArcGIS.ADF.Web.UI.WebControls.Tool CreateInputByMapTool() { ESRI.ArcGIS.ADF.Web.UI.WebControls.Tool selectInputByMapTool = new ESRI.ArcGIS.ADF.Web.UI.WebControls.Tool(); selectInputByMapTool.Name = "SearchAreaBySelection"; selectInputByMapTool.ServerActionAssembly = "FindNearTask_CSharp"; selectInputByMapTool.ServerActionClass = "FindNearTask_CSharp.SearchAreaBySelection"; selectInputByMapTool.ToolTip = "Select features to search near"; selectInputByMapTool.ClientAction = ESRI.ArcGIS.ADF.Web.UI.WebControls.MapClientToolAction.DragRectangle.ToString(); selectInputByMapTool.DefaultImage = ResourceUtility.GetImage("selectFeature.gif", this, typeof(FindNearTask)); selectInputByMapTool.SelectedImage = ResourceUtility.GetImage("selectFeature_selected.gif", this, typeof(FindNearTask)); selectInputByMapTool.HoverImage = ResourceUtility.GetImage("selectFeature_hover.gif", this, typeof(FindNearTask)); return selectInputByMapTool; } // Creates the command for clearing task input geometry from the map private ESRI.ArcGIS.ADF.Web.UI.WebControls.Command CreateClearInputCommand() { ESRI.ArcGIS.ADF.Web.UI.WebControls.Command clearInputCommand = new ESRI.ArcGIS.ADF.Web.UI.WebControls.Command(); clearInputCommand.Name = "ClearInput"; clearInputCommand.ServerActionAssembly = "FindNearTask_CSharp"; clearInputCommand.ServerActionClass = "FindNearTask_CSharp.ClearInput"; clearInputCommand.ToolTip = "Clear search area features and buffers from the map"; clearInputCommand.DefaultImage = ResourceUtility.GetImage("clearInput.gif", this, typeof(FindNearTask)); clearInputCommand.SelectedImage = ResourceUtility.GetImage("clearInput_selected.gif", this, typeof(FindNearTask)); clearInputCommand.HoverImage = ResourceUtility.GetImage("clearInput_hover.gif", this, typeof(FindNearTask)); return clearInputCommand; } // Creates the controls for specifying the layer to select features from for task input private void CreateSelectionLayerControls() { _selectionLayerLabel = new System.Web.UI.WebControls.Label(); _selectionLayerLabel.ID = "SelectionLayerLabel"; _selectionLayerLabel.Text = "Selection Layer:"; _selectionLayerLabel.Style[System.Web.UI.HtmlTextWriterStyle.WhiteSpace] = "nowrap"; _selectionLayerLabel.Style[System.Web.UI.HtmlTextWriterStyle.PaddingRight] = "5px"; _selectionLayerLabel.Style[System.Web.UI.HtmlTextWriterStyle.Display] = "none"; _selectionLayerDropDownList = new System.Web.UI.WebControls.DropDownList(); _selectionLayerDropDownList.ID = "SelectionLayerDropDownList"; _selectionLayerDropDownList.Style[System.Web.UI.HtmlTextWriterStyle.Display] = "none"; } // Creates the checkbox determining whether newly defined search areas are merged with those previously defined private System.Web.UI.WebControls.CheckBox CreateAddToInputCheckbox() { System.Web.UI.WebControls.CheckBox addToInputCheckbox = new System.Web.UI.WebControls.CheckBox(); addToInputCheckbox.ID = "AddToInputCheckbox"; addToInputCheckbox.Text = "Add New Search Areas to Previous"; addToInputCheckbox.Checked = true; addToInputCheckbox.Font.Bold = false; addToInputCheckbox.Style[System.Web.UI.HtmlTextWriterStyle.WhiteSpace] = "nowrap"; addToInputCheckbox.Attributes["onclick"] = "addToInputClicked()"; return addToInputCheckbox; } // Creates the label for the search distance textbox private System.Web.UI.WebControls.Label CreateSearchDistanceLabel() { System.Web.UI.WebControls.Label label = new System.Web.UI.WebControls.Label(); label.Text = "Search Distance:"; label.Style[System.Web.UI.HtmlTextWriterStyle.PaddingRight] = "5px"; label.Style[System.Web.UI.HtmlTextWriterStyle.WhiteSpace] = "nowrap"; return label; } // Creates and populates the search distance textbox and units drop-down list private void CreateSearchDistanceControls() { // Instantiate the search distance textbox _searchDistanceTextBox = new System.Web.UI.WebControls.TextBox(); _searchDistanceTextBox.ID = "SearchDistanceTextBox"; _searchDistanceTextBox.Width = new System.Web.UI.WebControls.Unit(75, System.Web.UI.WebControls.UnitType.Pixel); // If the search distance has been defined, use it to initialize the textbox. Otherwise, // leave it empty. _searchDistanceTextBox.Text = float.IsNaN(TaskInput.SearchDistance) ? string.Empty : TaskInput.SearchDistance.ToString(); _searchDistanceTextBox.Attributes.Add("onclick", "updateSearchArea()"); _searchDistanceTextBox.Attributes.Add("onchange", "updateSearchArea()"); // Get the map functionality for the primary map resource ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality primaryResourceMapFunctionality = this.MapInstance.GetFunctionality(MapInstance.PrimaryMapResource); // Set the task's input units to those of the primary map resource if (this.TaskInput.Units == null) this.TaskInput.Units = primaryResourceMapFunctionality.Units.ToString(); _unitsDropDownList = new System.Web.UI.WebControls.DropDownList(); _unitsDropDownList.ID = "UnitsDropDownList"; // Add all the ArcGIS Server unit types to the units drop-down list except for unknown, points, // and decimal degress System.Array adfUnitArray = System.Enum.GetValues(typeof(ESRI.ArcGIS.ADF.Web.DataSources.Units)); int selectedIndex = 0; int dropDownIndex = -1; foreach (int i in adfUnitArray) { string unit = adfUnitArray.GetValue(i).ToString(); if ((unit != "Unknown") && (unit != "DecimalDegrees") && (unit != "Points")) { _unitsDropDownList.Items.Add(unit); dropDownIndex++; } if (unit == this.TaskInput.Units) selectedIndex = dropDownIndex; } _unitsDropDownList.SelectedIndex = selectedIndex; // Specify JavaScript functions to call when the drop-down list is clicked and a new item is selected _unitsDropDownList.Attributes.Add("onchange", "updateSearchArea()"); } // Creates the label for the search layer drop-down list private System.Web.UI.WebControls.Label CreateSearchLayerLabel() { System.Web.UI.WebControls.Label label = new System.Web.UI.WebControls.Label(); label.ID = "SearchLayerLabel"; label.Text = "Search Layer:"; label.Style[System.Web.UI.HtmlTextWriterStyle.WhiteSpace] = "nowrap"; label.Style[System.Web.UI.HtmlTextWriterStyle.PaddingRight] = "5px"; return label; } // Creates and populates the search layer drop-down list private void CreateSearchLayerDropDownList() { // Instantiate the search layer drop-down list _searchLayerDropDownList = new System.Web.UI.WebControls.DropDownList(); _searchLayerDropDownList.ID = "SearchLayerDropDownList"; // Wire the JavaScript function updateSearchLayer to the list's onchange event _searchLayerDropDownList.Attributes.Add("onchange", "updateSearchLayer(this);"); // Make sure the search layer hasn't already been initialized before adding layers to the drop-down list if (this.TaskInput.SearchLayer == null) { // Dictionaries to hold the names and IDs of queryable layers System.Collections.Generic.Dictionary<string, string[]> layerNamesByResourceDictionary; System.Collections.Generic.Dictionary<string, string[]> layerIDsByResourceDictionary; // Get the names and IDs of all the queryable layers referenced by the buddied map resource manager this.GetQueryableLayers(MapInstance.MapResourceManagerInstance, out layerNamesByResourceDictionary, out layerIDsByResourceDictionary); // Loop through all the items in the layer names dictionary, adding each to the search layer and // selection layer lists foreach (System.Collections.Generic.KeyValuePair<string, string[]> layerNamesPair in layerNamesByResourceDictionary) { // Get the name of the resource from the current key value pair string resourceName = layerNamesPair.Key; // Get the array of layer names for the current resource string[] layerNamesArray = layerNamesPair.Value; // Loop through the names, creating a tree view plus node below the current resource node for each for (int i = 0; i < layerNamesArray.Length; i++) { // Get the layer ID for the current layer string layerID = layerIDsByResourceDictionary[resourceName][i]; if (_searchLayerDropDownList.Items.Count == 0) { // Set the layer and resource input parameters based on the current node TaskInput.SearchResource = resourceName; TaskInput.SearchLayer = layerID; } // Create an item for the current layer and add it to the selection layer and search layer // drop-down lists. Specify the item's text as the layer name, and the item's value as the // name of the resource containing the layer and the layer ID, delimited by a comma. System.Web.UI.WebControls.ListItem layerListItem = new System.Web.UI.WebControls.ListItem(); layerListItem.Text = layerNamesArray[i]; layerListItem.Value = string.Format("{0},{1}", resourceName, layerID); _selectionLayerDropDownList.Items.Add(layerListItem); _searchLayerDropDownList.Items.Add(layerListItem); } } } } // Creates the Find button private void CreateFindButton() { // Instantiate the Find button and specify its text _findButton = new System.Web.UI.HtmlControls.HtmlInputButton(); _findButton.ID = "FindButton"; _findButton.Value = "Find"; // Construct JavaScript to execute the task string executeTaskJavaScript = string.Format(@" executeTask('',""{0}"");", this.CallbackFunctionString, _taskToolbar.ClientID, MapInstance.ClientID); // Wire the JavaScript to execute when the Find button is clicked _findButton.Attributes.Add("onclick", executeTaskJavaScript); } // Creates the activity indicator div, which contains the image and label to be shown when the search // area is being updated private void CreateActivityIndicatorDiv() { // Create a div to hold the activity indicator image and label _activityIndicatorDiv = new System.Web.UI.HtmlControls.HtmlGenericControl("div"); _activityIndicatorDiv.ID = "ActivityIndicatorDiv"; _activityIndicatorDiv.Style[System.Web.UI.HtmlTextWriterStyle.Display] = "none"; // Create an HTML image control and initialize it with the activity indicator gif System.Web.UI.HtmlControls.HtmlImage activityIndicator = new System.Web.UI.HtmlControls.HtmlImage(); string activityIndicatorUrl = ESRI.ArcGIS.ADF.Web.UI.WebControls.ResourceUtility.GetImage( "callbackActivityIndicator.gif", this, typeof(ESRI.ArcGIS.ADF.Web.UI.WebControls.FloatingPanel), "Runtime"); activityIndicator.Src = activityIndicatorUrl; activityIndicator.Style[System.Web.UI.HtmlTextWriterStyle.PaddingRight] = "5px"; // Add the image to the div _activityIndicatorDiv.Controls.Add(activityIndicator); // Create the activity label and add it to the div System.Web.UI.WebControls.Label label = new System.Web.UI.WebControls.Label(); label.Font.Bold = false; label.ForeColor = System.Drawing.Color.Gray; label.Font.Italic = true; label.Text = "Updating Search Area..."; _activityIndicatorDiv.Controls.Add(label); } #endregion #region GeoSpatial Utility Methods // Calculates the buffer of the input geometries private ESRI.ArcGIS.ADF.Web.Geometry.Geometry BufferGeometries( ESRI.ArcGIS.ADF.Web.Geometry.Geometry[] adfInputGeometryArray, float bufferDistance, string units) { // Put the ArcGIS Server SOAP polygon in an ArcGIS Server SOAP geometry array to pass to the // buffer operation ESRI.ArcGIS.ADF.ArcGISServer.Geometry[] agsSoapInputGeometryArray = new ESRI.ArcGIS.ADF.ArcGISServer.Geometry[adfInputGeometryArray.Length]; for (int i = 0; i < adfInputGeometryArray.Length; i++) agsSoapInputGeometryArray[i] = ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.Converter.FromAdfGeometry(adfInputGeometryArray[i]); // Get a reference to an ArcGIS Server Geometry service ESRI.ArcGIS.ADF.ArcGISServer.GeometryServerProxy geometryServerProxy = new ESRI.ArcGIS.ADF.ArcGISServer.GeometryServerProxy(this.GeometryServiceUrl); // Get a spatial reference in which to perform the buffer operation. This spatial reference // is explicitly intialized based on the user-drawn polygon so that there is minimal projection // related buffer distortion ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference agsSoapBufferSpatialReference = this.CreateOperationSpatialReference(agsSoapInputGeometryArray, geometryServerProxy); // Use the units specified by the user to create an ArcGIS Server LinearUnit object ESRI.ArcGIS.ADF.ArcGISServer.LinearUnit agsSoapBufferUnits = new ESRI.ArcGIS.ADF.ArcGISServer.LinearUnit(); agsSoapBufferUnits.WKID = this.GetWkidByUnitName(units); agsSoapBufferUnits.WKIDSpecified = true; // Get the user-specified buffer distance and put it in an array to pass to the buffer // operation. If the user did not specify a distance, initialize the distance to zero. double[] bufferDistances = new double[1]; bufferDistances[0] = System.Convert.ToDouble(bufferDistance); ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference agsSoapInputSpatialReference = this.GetSpatialReference(agsSoapInputGeometryArray[0]); // Execute the buffer operation via the geometry service ESRI.ArcGIS.ADF.ArcGISServer.Geometry[] agsBufferGeometryArray = geometryServerProxy.Buffer( agsSoapInputSpatialReference, agsSoapBufferSpatialReference, agsSoapInputSpatialReference, bufferDistances, agsSoapBufferUnits, true, agsSoapInputGeometryArray); // Retrieve the buffer polygon from the array of result geometries ESRI.ArcGIS.ADF.Web.Geometry.Geometry adfBufferGeometry = ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.Converter.ToAdfGeometry(agsBufferGeometryArray[0]); if (adfBufferGeometry.SpatialReference == null) adfBufferGeometry.SpatialReference = adfInputGeometryArray[0].SpatialReference; return adfBufferGeometry; } // Returns the well-known ID of the passed-in unit private int GetWkidByUnitName(string unitName) { int wkid = -1; switch (unitName) { case "Inches": wkid = 109009; break; case "Feet": wkid = 9003; break; case "Yards": wkid = 109002; break; case "Miles": wkid = 9035; break; case "NauticalMiles": wkid = 9030; break; case "Millimeters": wkid = 109007; break; case "Centimeters": wkid = 109006; break; case "Meters": wkid = 9001; break; case "Kilometers": wkid = 9036; break; case "Decimeters": wkid = 109005; break; default: // default is Kilometers wkid = 9036; break; } return wkid; } // Creates a spatial reference that minimizes distortion in the vicinity of the passed-in geometriess private ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference CreateOperationSpatialReference( ESRI.ArcGIS.ADF.ArcGISServer.Geometry[] agsSoapGeometryArray, ESRI.ArcGIS.ADF.ArcGISServer.GeometryServerProxy geometryServerProxy) { // Get the polygon's minimum enclosing rectangle (MER) ESRI.ArcGIS.ADF.ArcGISServer.EnvelopeN agsSoapBoundingEnvelope = GetBoundingExtent(agsSoapGeometryArray); // If the input polygon's spatial reference uses a projected coordinate system, project the MER to a // geographic coordinate system (WGS 1984 in this case). We do this because the MER's coordinates // will be used to initialize the datum of the operation spatial reference ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference agsSoapSpatialReference = this.GetSpatialReference(agsSoapGeometryArray[0]); if (agsSoapSpatialReference is ESRI.ArcGIS.ADF.ArcGISServer.ProjectedCoordinateSystem) { // Create an ArcGIS Server spatial reference initalized to use the WGS 1984 coordinate system ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference agsSoapGeographicSpatialReference = new ESRI.ArcGIS.ADF.ArcGISServer.GeographicCoordinateSystem(); agsSoapGeographicSpatialReference.WKID = 4326; agsSoapGeographicSpatialReference.WKIDSpecified = true; // Place the input MER in an array for the project operation ESRI.ArcGIS.ADF.ArcGISServer.Geometry[] agsSoapInputGeometryArray = new ESRI.ArcGIS.ADF.ArcGISServer.Geometry[1]; agsSoapInputGeometryArray[0] = agsSoapBoundingEnvelope; // Execute the projection ESRI.ArcGIS.ADF.ArcGISServer.Geometry[] agsSoapOutputGeometryArray = geometryServerProxy.Project(agsSoapSpatialReference, agsSoapGeographicSpatialReference, true, null, null, agsSoapInputGeometryArray); // Retrieve the projected MER from the results array agsSoapBoundingEnvelope = agsSoapOutputGeometryArray[0] as ESRI.ArcGIS.ADF.ArcGISServer.EnvelopeN; } // Get the latitude (Y coordinate) at the center of the MER double centerLatitude = agsSoapBoundingEnvelope.YMax - (agsSoapBoundingEnvelope.YMax - agsSoapBoundingEnvelope.YMin) / 2; // Create the definition string for the operation spatial reference's coordinate system. We will use // the Hotine Oblique Mercator coordinate system because it lends itself well to minimizing operational // distortion anywhere on the earth string hotineObliqueMercatorDefinition = @" PROJCS[""World_Hotine"", GEOGCS[""GCS_WGS_1984"", DATUM[""D_WGS_1984"", SPHEROID[""WGS_1984"",6378137.0,298.257223563]], PRIMEM[""Greenwich"",0.0], UNIT[""Degree"",0.0174532925199433]], PROJECTION[""Hotine_Oblique_Mercator_Two_Point_Natural_Origin""], PARAMETER[""False_Easting"",0.0], PARAMETER[""False_Northing"",0.0], PARAMETER[""Latitude_Of_1st_Point"",{0}], PARAMETER[""Latitude_Of_2nd_Point"",{1}], PARAMETER[""Scale_Factor"",1.0], PARAMETER[""Longitude_Of_1st_Point"",{2}], PARAMETER[""Longitude_Of_2nd_Point"",{3}], PARAMETER[""Latitude_Of_Center"",{4}], UNIT[""Meter"",1.0]]"; // Specify the relevant coordinates of the MER for the coordinate system's datum parameters string customHotineObliqueCylindricalMercator = string.Format( hotineObliqueMercatorDefinition, agsSoapBoundingEnvelope.YMin, agsSoapBoundingEnvelope.YMax, agsSoapBoundingEnvelope.XMin, agsSoapBoundingEnvelope.XMax, centerLatitude); // Create the spatial reference ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference agsSoapBufferSpatialReference = geometryServerProxy.FindSRByWKT(customHotineObliqueCylindricalMercator, null, true, true); return agsSoapBufferSpatialReference; } // Returns the spatial reference of an ArcGIS Server SOAP Geometry private ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference GetSpatialReference( ESRI.ArcGIS.ADF.ArcGISServer.Geometry agsSoapGeometry) { ESRI.ArcGIS.ADF.ArcGISServer.SpatialReference agsSoapSpatialReference = null; if (agsSoapGeometry is ESRI.ArcGIS.ADF.ArcGISServer.PolygonN) { ESRI.ArcGIS.ADF.ArcGISServer.PolygonN agsSoapPolygon = agsSoapGeometry as ESRI.ArcGIS.ADF.ArcGISServer.PolygonN; agsSoapSpatialReference = agsSoapPolygon.SpatialReference; } else if (agsSoapGeometry is ESRI.ArcGIS.ADF.ArcGISServer.PolylineN) { ESRI.ArcGIS.ADF.ArcGISServer.PolylineN agsSoapPolyline = agsSoapGeometry as ESRI.ArcGIS.ADF.ArcGISServer.PolylineN; agsSoapSpatialReference = agsSoapPolyline.SpatialReference; } else if (agsSoapGeometry is ESRI.ArcGIS.ADF.ArcGISServer.PointN) { ESRI.ArcGIS.ADF.ArcGISServer.PointN agsSoapPoint = agsSoapGeometry as ESRI.ArcGIS.ADF.ArcGISServer.PointN; agsSoapSpatialReference = agsSoapPoint.SpatialReference; } return agsSoapSpatialReference; } // Gets the bounding extent of the passed-in ArcGIS Server SOAP geometries private ESRI.ArcGIS.ADF.ArcGISServer.EnvelopeN GetBoundingExtent( ESRI.ArcGIS.ADF.ArcGISServer.Geometry[] agsSoapGeometryArray) { // Instantiate an envelope with max values minimized and min values maximized ESRI.ArcGIS.ADF.ArcGISServer.EnvelopeN agsSoapBoundingBox = new ESRI.ArcGIS.ADF.ArcGISServer.EnvelopeN(); agsSoapBoundingBox.XMin = double.MaxValue; agsSoapBoundingBox.XMax = double.MinValue; agsSoapBoundingBox.YMin = double.MaxValue; agsSoapBoundingBox.YMax = double.MinValue; for (int i = 0; i < agsSoapGeometryArray.Length; i++) { ESRI.ArcGIS.ADF.ArcGISServer.Geometry agsSoapGeometry = agsSoapGeometryArray[i]; if (agsSoapGeometry is ESRI.ArcGIS.ADF.ArcGISServer.PolygonN) { ESRI.ArcGIS.ADF.ArcGISServer.PolygonN agsSoapPolygon = agsSoapGeometry as ESRI.ArcGIS.ADF.ArcGISServer.PolygonN; // Iterate through all the polygon's vertices for (int j = 0; j < agsSoapPolygon.RingArray.Length; j++) { ESRI.ArcGIS.ADF.ArcGISServer.Ring agsSoapRing = agsSoapPolygon.RingArray[j]; for (int k = 0; k < agsSoapRing.PointArray.Length; k++) { // For each vertex, expand the bounds of the minimum enclosing rectangle with the // vertex's coordinates if they fall outside the rectangle's current bounds ESRI.ArcGIS.ADF.ArcGISServer.PointN agsSoapCurrentPoint = agsSoapRing.PointArray[k] as ESRI.ArcGIS.ADF.ArcGISServer.PointN; if (agsSoapCurrentPoint.X < agsSoapBoundingBox.XMin) agsSoapBoundingBox.XMin = agsSoapCurrentPoint.X; else if (agsSoapCurrentPoint.X > agsSoapBoundingBox.XMax) agsSoapBoundingBox.XMax = agsSoapCurrentPoint.X; if (agsSoapCurrentPoint.Y < agsSoapBoundingBox.YMin) agsSoapBoundingBox.YMin = agsSoapCurrentPoint.Y; else if (agsSoapCurrentPoint.Y > agsSoapBoundingBox.YMax) agsSoapBoundingBox.YMax = agsSoapCurrentPoint.Y; } } } else if (agsSoapGeometry is ESRI.ArcGIS.ADF.ArcGISServer.PolylineN) { ESRI.ArcGIS.ADF.ArcGISServer.PolylineN agsSoapPolyline = agsSoapGeometry as ESRI.ArcGIS.ADF.ArcGISServer.PolylineN; // Iterate through all the polyline's vertices for (int j = 0; j < agsSoapPolyline.PathArray.Length; j++) { ESRI.ArcGIS.ADF.ArcGISServer.Path agsSoapPath = agsSoapPolyline.PathArray[j]; for (int k = 0; k < agsSoapPath.PointArray.Length; k++) { // For each vertex, expand the bounds of the minimum enclosing rectangle with the // vertex's coordinates if they fall outside the rectangle's current bounds ESRI.ArcGIS.ADF.ArcGISServer.PointN agsSoapCurrentPoint = agsSoapPath.PointArray[k] as ESRI.ArcGIS.ADF.ArcGISServer.PointN; if (agsSoapCurrentPoint.X < agsSoapBoundingBox.XMin) agsSoapBoundingBox.XMin = agsSoapCurrentPoint.X; else if (agsSoapCurrentPoint.X > agsSoapBoundingBox.XMax) agsSoapBoundingBox.XMax = agsSoapCurrentPoint.X; if (agsSoapCurrentPoint.Y < agsSoapBoundingBox.YMin) agsSoapBoundingBox.YMin = agsSoapCurrentPoint.Y; else if (agsSoapCurrentPoint.Y > agsSoapBoundingBox.YMax) agsSoapBoundingBox.YMax = agsSoapCurrentPoint.Y; } } } else if (agsSoapGeometry is ESRI.ArcGIS.ADF.ArcGISServer.PointN) { ESRI.ArcGIS.ADF.ArcGISServer.PointN agsSoapPoint = agsSoapGeometry as ESRI.ArcGIS.ADF.ArcGISServer.PointN; agsSoapBoundingBox.XMin = agsSoapPoint.X - .1; agsSoapBoundingBox.XMax = agsSoapPoint.X + .1; agsSoapBoundingBox.YMin = agsSoapPoint.Y - .1; agsSoapBoundingBox.YMax = agsSoapPoint.Y + .1; } } return agsSoapBoundingBox; } #endregion #region TaskResultNode Utility Methods // Retrieves a GraphicsLayerNode that is an ancestor or descendant of the passed-in node, if available private ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode GetRelatedGraphicsLayerNode( ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode node) { // Check whether the passed-in node is a GraphicsLayerNode ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode graphicsLayerNode = node as ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode; // Check whether the passed-in node has an ancestor GraphicsLayerNode if (graphicsLayerNode == null) graphicsLayerNode = this.FindParentGraphicsLayerNode(node); // Check whether the passed-in node has a descendant GraphicsLayerNode if (graphicsLayerNode == null) graphicsLayerNode = this.FindChildGraphicsLayerNode(node); return graphicsLayerNode; } // Retrieves a GraphicsLayerNode that is a descendant of the passed-in node, if available private ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode FindChildGraphicsLayerNode( ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode node) { ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode graphicsLayerNode = node as ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode; if (graphicsLayerNode == null && node.Nodes.Count > 0) { foreach (ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode childNode in node.Nodes) { graphicsLayerNode = this.FindChildGraphicsLayerNode(childNode); if (graphicsLayerNode != null) break; } } return graphicsLayerNode; } // Retrieves a GraphicsLayerNode that is an ancestor of the passed-in node, if available private ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode FindParentGraphicsLayerNode( ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode node) { ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode graphicsLayerNode = node as ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode; if (graphicsLayerNode == null && node.Parent is ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode) graphicsLayerNode = this.FindParentGraphicsLayerNode(node.Parent as ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode); return graphicsLayerNode; } // Retrieves FeatureNodes that are descendants of the passed-in node if available private void FindChildFeatureNodes(ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode treeViewPlusNode, ref System.Collections.Generic.List<ESRI.ArcGIS.ADF.Web.UI.WebControls.FeatureNode> featureNodes) { ESRI.ArcGIS.ADF.Web.UI.WebControls.FeatureNode featureNode = treeViewPlusNode as ESRI.ArcGIS.ADF.Web.UI.WebControls.FeatureNode; if (featureNode != null) featureNodes.Add(featureNode); if (treeViewPlusNode.Nodes.Count > 0) { foreach (ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode childNode in treeViewPlusNode.Nodes) this.FindChildFeatureNodes(childNode, ref featureNodes); } return; } #endregion #region Asynchronous Request Utility Methods // Retrieves the control that initiated the asynchronous request private System.Web.UI.Control GetCallingControl(System.Web.UI.Page page) { if (page == null) return null; if (page.IsCallback) { string controlID = page.Request.Params["__CALLBACKID"]; System.Web.UI.Control control = page.FindControl(controlID); return control; } // For 9.3 we could be using a partial postback instead else if (page.IsPostBack && System.Web.UI.ScriptManager.GetCurrent(page) != null && System.Web.UI.ScriptManager.GetCurrent(page).IsInAsyncPostBack) { string controlID = System.Web.UI.ScriptManager.GetCurrent(page).AsyncPostBackSourceElementID; System.Web.UI.Control control = page.FindControl(controlID); return control; } else return null; //Not an asyncronous request } // Copies the passed-in callback results to the callback results collection of the control that initiated // the asynchronous request private void CopyCallbackResultsToCaller( ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResultCollection callbackResults) { System.Web.UI.Control callingControl = this.GetCallingControl(this.Page); if (callingControl is ESRI.ArcGIS.ADF.Web.UI.WebControls.CompositeControl) { ESRI.ArcGIS.ADF.Web.UI.WebControls.CompositeControl compositeControl = callingControl as ESRI.ArcGIS.ADF.Web.UI.WebControls.CompositeControl; compositeControl.CallbackResults.CopyFrom(callbackResults); } else if (callingControl is ESRI.ArcGIS.ADF.Web.UI.WebControls.WebControl) { ESRI.ArcGIS.ADF.Web.UI.WebControls.WebControl webControl = callingControl as ESRI.ArcGIS.ADF.Web.UI.WebControls.WebControl; webControl.CallbackResults.CopyFrom(callbackResults); } } #endregion #endregion } }