Common_MapTips_VBNet\App_Code\AttributesOnDemandTask.vb
' Copyright 2010 ESRI ' ' All rights reserved under the copyright laws of the United States ' and applicable international laws, treaties, and conventions. ' ' You may freely redistribute and use this sample code, with or ' without modification, provided you include the original copyright ' notice and use restrictions. ' ' See the use restrictions. ' Imports Microsoft.VisualBasic Imports System Namespace ESRI.ADF.Samples.CustomTasks Public Class AttributesOnDemandTask Inherits ESRI.ArcGIS.ADF.Tasks.QueryAttributesTask #Region "Instance Variable Declarations" ' Stores a reference to the buddied TaskResults Control Private m_taskResults As ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults = Nothing ' Tracks whether the current page request has routed through ExecuteTask Private _taskExecuted As Boolean = False #End Region #Region "ASP.NET WebControl Life Cycle Event Handlers" Protected Overrides Sub CreateChildControls() MyBase.CreateChildControls() ' Add a handler to the buddied TaskResults Control's NodeAdded event AddHandler TaskResultsInstance.NodeAdded, AddressOf TaskResultsInstance_NodeAdded End Sub #End Region #Region "Web ADF Control Event Handlers" ' Retrieves the results graphics layer and enables Attribute-on-demand MapTips. Needs to be done here for extended tasks ' because the results graphics layer available in ExecuteTask is replaced during subsequent task result node creation. Private Sub TaskResultsInstance_NodeAdded(ByVal sender As Object, ByVal args As ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNodeEventArgs) ' Check whether the currently added node has a parent or child graphics layer and the task has executed during the ' current request Dim graphicsLayerNode As ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode = Me.GetRelatedGraphicsLayerNode(args.Node) If graphicsLayerNode IsNot Nothing AndAlso Me._taskExecuted Then ' Retrieve the task's layerFormat Dim layerFormat As ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerFormat = ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerFormat.FromMapResourceManager(Me.TaskResultsInstance.MapInstance.MapResourceManagerInstance, Me.PredefinedQuery.MapResource, Me.PredefinedQuery.LayerID) ' Iterate through the fields of the LayerFormat and create the HTML markup for the MapTips content area that ' will be used after attribute data has been retrieved Dim uniqueIDField As String = Nothing Dim currentTemplateRow As String = Nothing Dim defaultTemplateRows As New System.Collections.Generic.List(Of String)() Dim hasAttributesTemplate As String = "<table>" For Each fieldInfo As ESRI.ArcGIS.ADF.Web.DataSources.FieldInfo In layerFormat.Fields If fieldInfo.Visible Then currentTemplateRow = "<tr><td style='font-weight:bold; border-bottom: solid 1px gray; " & "border-right: solid 1px gray;'>{0}</td>" & "<td style='border-bottom: solid 1px gray; border-right: solid 1px gray;'>{{{{@{1}}}}}</td></tr>" currentTemplateRow = String.Format(currentTemplateRow, fieldInfo.Alias, fieldInfo.Name) defaultTemplateRows.Add(currentTemplateRow) End If ' If the current field is a unique identifier, store a reference to the field name If graphicsLayerNode.Layer.Columns(fieldInfo.Name).Unique Then uniqueIDField = fieldInfo.Name End If Next fieldInfo For Each templateRow As String In defaultTemplateRows hasAttributesTemplate &= templateRow Next templateRow hasAttributesTemplate &= "</table>" ' Get the URL of the Web ADF activity indicator Dim activityIndicatorUrl As String = ESRI.ArcGIS.ADF.Web.UI.WebControls.ResourceUtility.GetImage("callbackActivityIndicator.gif", Me, GetType(ESRI.ArcGIS.ADF.Web.UI.WebControls.FloatingPanelTask), "Runtime") ' Create the HTML markup for the MapTips content area while attribute data is being retrieved Dim retrievingAttributesTemplate As String = "<div style='white-space:nowrap; font-family:Arial; " & "font-style:italic; font-size:10pt; color:gray;'><img src='{0}' />Retrieving Attribute Data</div>" retrievingAttributesTemplate = String.Format(retrievingAttributesTemplate, activityIndicatorUrl) ' Get a reference to the node's graphics layer as a FeatureGraphicsLayer Dim featureGraphicsLayer As ESRI.ArcGIS.ADF.Web.Display.Graphics.FeatureGraphicsLayer = TryCast(graphicsLayerNode.Layer, ESRI.ArcGIS.ADF.Web.Display.Graphics.FeatureGraphicsLayer) ' Construct the client-side GraphicFeatureGroup ID of the results graphics layer. Note that this is only necessary ' for extended out-of-the-box tasks. Otherwise, Map::GetGraphicsLayerClientID or MapTips::GraphicsLayerClientID can ' be used. Dim graphicsLayerID As String = String.Format("{0}_{1} {2} Results_{3}", Me.TaskResultsInstance.MapInstance.ClientID, Me.TaskResultsInstance.ClientID, featureGraphicsLayer.FeatureType.ToString(), graphicsLayerNode.Layer.TableName) Dim id As String = Me.TaskResultsInstance.MapInstance.GetGraphicsLayerClientID(featureGraphicsLayer) ' JavaScript to call the attributes-on-demand MapTips initialization method. Here the content templates are ' explicitly defined. If they are not, default templates will be used. Dim enableAttributesOnDemandJavaScript As String = "" & ControlChars.CrLf & " window.setTimeout(""var graphicFeatureGroup = $find('{0}');"" +" & ControlChars.CrLf & " ""var retrievingAttributesTemplate = String.format(\""{1}\"", graphicFeatureGroup.get_id());"" +" & ControlChars.CrLf & " ""var hasAttributesTemplate = String.format(\""{2}\"", graphicFeatureGroup.get_id());"" +" & ControlChars.CrLf & " ""graphicFeatureGroup.setupMapTipsAttributesOnDemand(retrievingAttributesTemplate, hasAttributesTemplate,"" +" & ControlChars.CrLf & " ""'{3}', '{4}', '{5}', \""{6}\"");"", 0);" enableAttributesOnDemandJavaScript = String.Format(enableAttributesOnDemandJavaScript, graphicsLayerID, retrievingAttributesTemplate, hasAttributesTemplate, uniqueIDField, Me.PredefinedQuery.LayerID, Me.PredefinedQuery.MapResource, Me.CallbackFunctionString) Dim enableAttributesOnDemandCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(enableAttributesOnDemandJavaScript) Me.CallbackResults.Add(enableAttributesOnDemandCallbackResult) End If End Sub #End Region #Region "Task Overrides" Public Overrides Sub ExecuteTask() ' Create a default set of results MyBase.ExecuteTask() Me._taskExecuted = True End Sub Public Overrides Function GetCallbackResult() As String Dim callbackArgs As System.Collections.Specialized.NameValueCollection = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection(Me.CallbackEventArgument) ' Check whether the callback event argument indicates retrieval of MapTips attributes If callbackArgs("EventArg") = "retrieveMapTipsAttributes" Then ' === USED ONLY FOR DEMONSTRATION - REMOVE FOR PRODUCTION PURPOSES == ' Suspend the current thread to allow the retrieving attributes indicator to display System.Threading.Thread.Sleep(1000) MyBase.GetCallbackResult() ' Get a reference to the resource that was passed as part of the callback arguments Dim commonMapFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality = Me.TaskResultsInstance.MapInstance.GetFunctionality(callbackArgs("ResourceName")) Dim gisResource As ESRI.ArcGIS.ADF.Web.DataSources.IGISResource = commonMapFunctionality.Resource ' Retrieve query functionality for the resource Dim commonQueryFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality = CType(gisResource.CreateFunctionality(GetType(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), Nothing), ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality) ' Initialize a query filter Dim adfQueryFilter As New ESRI.ArcGIS.ADF.Web.QueryFilter() adfQueryFilter.ReturnADFGeometries = False ' Create the query clause with information passed from the maptips in the callback adfQueryFilter.WhereClause = String.Format("{0} = {1}", callbackArgs("UniqueIDField"), callbackArgs("FeatureID")) ' Execute the query Dim resultsTable As System.Data.DataTable = commonQueryFunctionality.Query(Nothing, callbackArgs("LayerID"), adfQueryFilter) If resultsTable Is Nothing Then Return MyBase.GetCallbackResult() End If ' Create a JSON string with the results feature's attributes Dim jsonAttributes As String = "{ " For Each column As System.Data.DataColumn In resultsTable.Columns jsonAttributes &= String.Format("'{0}':'{1}', ", column.ColumnName, resultsTable.Rows(0)(column.ColumnName)) Next column jsonAttributes = String.Format("{0} }}", jsonAttributes.Substring(0, jsonAttributes.Length - 2)) ' JavaScript needed to apply the queried feature's attributes to the mapTips Dim updateAttributesJavaScript As String = String.Format("$find('{0}').get_mapTips().updateAttributes({1}, '{2}');", callbackArgs("GraphicFeatureGroupID"), jsonAttributes, callbackArgs("FeatureID")) Dim updateAttributesCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(updateAttributesJavaScript) Me.CallbackResults.Add(updateAttributesCallbackResult) Return Me.CallbackResults.ToString() Else Return MyBase.GetCallbackResult() End If End Function #End Region #Region "Instance Properties" ' Convenient access to the first TaskResults control in the Task's TaskResultsContainers collection Private ReadOnly Property TaskResultsInstance() As ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults Get ' Retrieve the TaskResults control if it has not already been If (m_taskResults Is Nothing) AndAlso (TaskResultsContainers(0) IsNot Nothing) Then m_taskResults = TryCast(ESRI.ArcGIS.ADF.Web.UI.WebControls.Utility.FindControl(TaskResultsContainers(0).Name, Page), ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults) End If Return m_taskResults End Get End Property #End Region #Region "Instance Methods" ' Retrieves a GraphicsLayerNode that is an ancestor or descendant of the passed-in node, if available Private Function GetRelatedGraphicsLayerNode(ByVal node As ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode) As ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode ' Check whether the passed-in node is a GraphicsLayerNode Dim graphicsLayerNode As ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode = TryCast(node, ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode) ' Check whether the passed-in node has an ancestor GraphicsLayerNode If graphicsLayerNode Is Nothing Then graphicsLayerNode = Me.FindParentGraphicsLayerNode(node) End If ' Check whether the passed-in node has a descendant GraphicsLayerNode If graphicsLayerNode Is Nothing Then graphicsLayerNode = Me.FindChildGraphicsLayerNode(node) End If Return graphicsLayerNode End Function ' Retrieves a GraphicsLayerNode that is a descendant of the passed-in node, if available Private Function FindChildGraphicsLayerNode(ByVal node As ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode) As ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode Dim graphicsLayerNode As ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode = TryCast(node, ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode) If graphicsLayerNode Is Nothing AndAlso node.Nodes.Count > 0 Then For Each childNode As ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode In node.Nodes graphicsLayerNode = Me.FindChildGraphicsLayerNode(childNode) If graphicsLayerNode IsNot Nothing Then Exit For End If Next childNode End If Return graphicsLayerNode End Function ' Retrieves a GraphicsLayerNode that is an ancestor of the passed-in node, if available Private Function FindParentGraphicsLayerNode(ByVal node As ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode) As ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode Dim graphicsLayerNode As ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode = TryCast(node, ESRI.ArcGIS.ADF.Web.UI.WebControls.GraphicsLayerNode) If graphicsLayerNode Is Nothing AndAlso TypeOf node.Parent Is ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode Then graphicsLayerNode = Me.FindParentGraphicsLayerNode(TryCast(node.Parent, ESRI.ArcGIS.ADF.Web.UI.WebControls.TreeViewPlusNode)) End If Return graphicsLayerNode End Function #End Region End Class End Namespace