Common Custom tasks
Common_CustomTasks_VBNet\QueryBuilderTask_VBNet\QueryBuilderTask.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
  ' Default markup inserted when the task is dragged from the toolbox onto a page in Visual Studio
  ' Image used to represent the task in a container (e.g. the Visual Studio toolbox)
  ' Class used to configure the task in ArcGIS Manager
  '[ESRI.ArcGIS.ADF.Web.UI.WebControls.WebConfigurator(typeof(QueryBuilderTaskWebConfigurator_VBNet))]
  ' Class used to configure the task in Visual Studio
  '[System.ComponentModel.Designer(typeof(QueryBuilderTaskDesigner_VBNet))]
  ' QueryBuilderTask's implementation
    <System.Web.UI.ToolboxData("<{0}:QueryBuilderTask runat=""server"" BackColor=""White""" & ControlChars.CrLf & "        BorderColor=""LightSteelBlue"" BorderStyle=""Outset"" BorderWidth=""1px"" Font-Names=""Verdana""" & ControlChars.CrLf & "        Font-Size=""8pt"" ForeColor=""Black"" TitleBarColor=""WhiteSmoke"" TitleBarHeight=""20px""" & ControlChars.CrLf & "        TitleBarSeparatorLine=""True"" Transparency=""35"" Width=""130px"" Title=""Query Builder""" & ControlChars.CrLf & "        HeightResizable=""False"" WidthResizable=""False"">" & ControlChars.CrLf & "        </{0}:QueryBuilderTask>"), System.Drawing.ToolboxBitmap(GetType(QueryBuilderTask)), ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientTaskDefinitionExplicit()> _
    Public Class QueryBuilderTask
        Inherits ESRI.ADF.Samples.CustomTasks.ScriptTask
#Region "Instance Variables - Controls Exposed to Client-Side Task"

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _layerDropDownList As System.Web.UI.HtmlControls.HtmlGenericControl

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _retrievingLayersDiv As System.Web.UI.HtmlControls.HtmlGenericControl

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _fieldDropDownList As System.Web.UI.HtmlControls.HtmlGenericControl

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _retrievingFieldsDiv As System.Web.UI.HtmlControls.HtmlGenericControl

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _operatorDropDownList As System.Web.UI.HtmlControls.HtmlGenericControl

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _sampleValueDropDownList As System.Web.UI.HtmlControls.HtmlGenericControl

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _retrievingSampleValuesDiv As System.Web.UI.HtmlControls.HtmlGenericControl

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _addToQueryButton As System.Web.UI.HtmlControls.HtmlInputButton

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _andButton As System.Web.UI.HtmlControls.HtmlInputButton

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _orButton As System.Web.UI.HtmlControls.HtmlInputButton

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _notButton As System.Web.UI.HtmlControls.HtmlInputButton

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _leftParenthesisButton As System.Web.UI.HtmlControls.HtmlInputButton

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _rightParenthesisButton As System.Web.UI.HtmlControls.HtmlInputButton

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _percentButton As System.Web.UI.HtmlControls.HtmlInputButton

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _underscoreButton As System.Web.UI.HtmlControls.HtmlInputButton

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _queryTextBox As System.Web.UI.WebControls.TextBox

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _clearQueryButton As System.Web.UI.HtmlControls.HtmlInputButton

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _doQueryButton As System.Web.UI.HtmlControls.HtmlInputButton

        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Private _executingQueryDiv As System.Web.UI.HtmlControls.HtmlGenericControl

#End Region

#Region "ASP.NET WebControl Life Cycle Event Overrides - CreateChildControls"

        ' Configures the task's interface
        Protected Overrides Sub CreateChildControls()
            MyBase.CreateChildControls()

            ' Call methods to instantiate task controls and place them in html tables for formatting

            ' Layers drop-down list
            Me.CreateDropDownListSection(_layerDropDownList, _retrievingLayersDiv, "Layers:", "Retrieving Layers...")
            ' Fields drop-down list
            Me.CreateDropDownListSection(_fieldDropDownList, _retrievingFieldsDiv, "Fields:", "Retrieving Fields...")
            ' Operators drop-down list
            Me.CreateDropDownListSection(_operatorDropDownList, "Operators:")
            ' Sample values drop-down list
            Me.CreateDropDownListSection(_sampleValueDropDownList, _retrievingSampleValuesDiv, "Sample Values:", "Retrieving Sample Values...")

            Me.CreateAddToQueryButtonSection()
            Me.CreateSeparator()
            Me.CreateOperatorButtonsSection()
            Me.CreateSeparator()
            Me.CreateQuerySection()
            Me.CreateQueryButtonsSection()
        End Sub

#End Region

#Region "Instance Methods"

#Region "Public Methods Exposed to Client-Side Task"

        ' Retrieves the layers for the current map and packages the properties of each that are
        ' required by the client-side task in a JSON array
        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Public Function GetJsonLayers() As String
            ' Add the opening bracket of the JSON array
            Dim jsonLayerArray As String = "[ "

            ' Iterate through the resources in the buddied map, extracting the layer information
            ' from each and adding it to the JSON array
            For Each mapResourceItem As ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceItem In Me.MapControl.MapResourceManagerInstance.ResourceItems
                ' If the current resource is a graphics resource and the ExcludeGraphicsResources
                ' property is true, skip to the next resource item
                If Me.ExcludeGraphicsResources AndAlso TypeOf mapResourceItem.Resource Is ESRI.ArcGIS.ADF.Web.DataSources.Graphics.MapResource Then
                    Continue For
                End If

                ' If the current resource does not support querying, skip to the next resource item
                If (Not mapResourceItem.Resource.SupportsFunctionality(GetType(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality))) Then
                    Continue For
                End If

                ' Get the resource's map functionality
                Dim commonMapFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality = Me.MapControl.GetFunctionality(mapResourceItem)

                ' Get the map's layers
                Dim layerIDsArray() As String
                Dim layerNamesArray() As String
                commonMapFunctionality.GetLayers(layerIDsArray, layerNamesArray)

                ' Loop through the layers.  For each, add a JSON object with the properties needed 
                ' by the client-side task
                For i As Integer = 0 To layerIDsArray.Length - 1
                    jsonLayerArray &= String.Format("{{ ""name"":""{0}"", ""id"":""{1}"", " & """mapResource"":""{2}"", ""map"":""{3}"" }}, ", layerNamesArray(i), layerIDsArray(i), mapResourceItem.Name, Me.Map)
                Next i
            Next mapResourceItem

            ' Remove trailing comma and add a closing square bracket
            If jsonLayerArray.Length > 2 Then
                jsonLayerArray = String.Format("{0} ]", jsonLayerArray.Substring(0, jsonLayerArray.Length - 2))
            End If

            Return jsonLayerArray
        End Function

        ' Retrieves the fields for the layer specified by the passed-in JSON and returns the
        ' properties of those fields in a JSON array
        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Public Function GetJsonFields(ByVal jsonLayer As String) As String
            ' Convert the passed-in JSON to a Dictionary object
            Dim javaScriptSerializer As New System.Web.Script.Serialization.JavaScriptSerializer()
            Dim layer As System.Collections.Generic.Dictionary(Of String, Object) = TryCast(javaScriptSerializer.DeserializeObject(jsonLayer), System.Collections.Generic.Dictionary(Of String, Object))

            ' Get the LayerFormat for the passed-in layer
            Dim mapResourceName As String = TryCast(layer("mapResource"), String)
            Dim layerID As String = TryCast(layer("id"), String)
            Dim layerFormat As ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerFormat = ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerFormat.FromMapResourceManager(Me.MapControl.MapResourceManagerInstance, mapResourceName, layerID)

            ' Add the opening bracket of the json Array
            Dim jsonFieldArray As String = "[ "

            ' Loop through all the fields, converting each visible one to JSON and adding it to
            ' the array string
            For Each fieldInfo As ESRI.ArcGIS.ADF.Web.DataSources.FieldInfo In layerFormat.Fields
                If fieldInfo.Visible Then
                    jsonFieldArray &= String.Format("{0},", fieldInfo.ToJson())
                End If
            Next fieldInfo

            ' Remove trailing comma and add closing square bracket
            If jsonFieldArray.Length > 2 Then
                jsonFieldArray = String.Format("{0} ]", jsonFieldArray.Substring(0, jsonFieldArray.Length - 1))
            End If
            Return jsonFieldArray
        End Function

        ' Retrieves values for the field, layer, and map resource specified.  Values are returned
        ' as a JSON array.
        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Public Function GetSampleValues(ByVal fieldName As String, ByVal layerID As String, ByVal mapResourceName As String) As String
            ' Execute a query with an empty where clause on the passed-in layer.  This will return
            ' all the features, subject to the service maximum.
            Dim valuesDataTable As System.Data.DataTable = Me.ExecuteQuery(Nothing, fieldName, layerID, mapResourceName)

            ' Replace periods in field name if necessary
            If fieldName <> valuesDataTable.Columns(0).ColumnName Then
                fieldName = fieldName.Replace(".", "_")
            End If

            ' Add the opening bracket of the JSON array that will store the values
            Dim jsonValueArray As String = "[ "

            ' Loop through the rows of the data table, adding the value of each for the specified
            ' field to the JSON array
            For i As Integer = 0 To valuesDataTable.Rows.Count - 1
                ' Get field value from current row
                Dim value As String = valuesDataTable.Rows(i)(fieldName).ToString()

                ' Escape single and double quotes, as these will otherwise short-circuit calls to eval 
                ' on the result that is returned to the client
                value = value.Replace("'", "\'")
                value = value.Replace("""", "\\""")

                ' Surround the value with quotes and add a trailing comma to format it as an item in a 
                ' JSON array
                value = String.Format("""{0}"",", value)

                ' If the value is not already in the array and is not empty, add it to the array
                If (jsonValueArray.IndexOf(value) < 0) AndAlso (value <> "") AndAlso (value <> " ") AndAlso (value <> "NaN") AndAlso (value IsNot Nothing) Then
                    jsonValueArray &= value
                End If
            Next i

            ' Remove trailing comma and add closing square bracket
            If jsonValueArray.Length > 2 Then
                jsonValueArray = String.Format("{0} ]", jsonValueArray.Substring(0, jsonValueArray.Length - 1))
            End If

            Return jsonValueArray
        End Function

        ' Executes a query as specified by the passed-in arguments and adds the results to the
        ' task's first buddied TaskResults container
        <ESRI.ADF.Samples.CustomTasks.ScriptTask.ClientMember()> _
        Public Sub DoQuery(ByVal queryExpression As String, ByVal layerID As String, ByVal mapResourceName As String)
            ' Execute the query with the specified parameters
            Dim resultsDataTable As System.Data.DataTable = Me.ExecuteQuery(queryExpression, Nothing, layerID, mapResourceName)

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

            ' Select each result so that its node is checked in the TaskResults control
            For Each dataRow As System.Data.DataRow In resultsGraphicsLayer.Rows
                dataRow(resultsGraphicsLayer.IsSelectedColumn) = True
            Next dataRow

            ' Retrieve the query layer's layerFormat and apply it to the results layer
            Dim layerFormat As ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerFormat = ESRI.ArcGIS.ADF.Web.UI.WebControls.LayerFormat.FromMapResourceManager(Me.MapControl.MapResourceManagerInstance, mapResourceName, layerID)
            layerFormat.Apply(resultsGraphicsLayer)

            ' Render the results on the client to enable callouts and highlighting
            resultsGraphicsLayer.RenderOnClient = True

            ' Create a DataSet and add the results to it
            Dim resultsDataSetName As String = String.Format("Query Results - {0}", resultsGraphicsLayer.TableName)
            Dim resultsDataSet As New System.Data.DataSet(resultsDataSetName)
            resultsDataSet.Tables.Add(resultsGraphicsLayer)

            ' Get the task's first buddied TaskResults control
            Dim taskResultsContainer As ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults = TryCast(ESRI.ArcGIS.ADF.Web.UI.WebControls.Utility.FindControl(Me.TaskResultsContainers(0).Name, Me.Page), ESRI.ArcGIS.ADF.Web.UI.WebControls.TaskResults)

            ' Make sure a TaskResults control was found
            If taskResultsContainer Is Nothing Then
                Return
            End If

            ' Display the query results.  Note the TaskResults container automatically handles
            ' adding results to its buddied Map.
            taskResultsContainer.DisplayResults(Nothing, Nothing, Nothing, resultsDataSet)

            ' Copy the task results callback results to the task so they are processed on the client.
            Me.CallbackResults.CopyFrom(taskResultsContainer.CallbackResults)
        End Sub

#End Region

#Region "Private Methods"

        ' Executes a query as specified by the passed-in parameters.  Note that queryExpression 
        ' and field name are nullable
        Private Function ExecuteQuery(ByVal queryExpression As String, ByVal fieldName As String, ByVal layerID As String, ByVal mapResourceName As String) As System.Data.DataTable
            ' Get the map resource having the passed-in name
            Dim commonMapResource As ESRI.ArcGIS.ADF.Web.DataSources.IMapResource = TryCast(Me.MapControl.MapResourceManagerInstance.ResourceItems.Find(mapResourceName).Resource, ESRI.ArcGIS.ADF.Web.DataSources.IMapResource)

            ' Create a query functionality from the map resource
            Dim commonQueryFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality = CType(commonMapResource.CreateFunctionality(GetType(ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality), "query"), ESRI.ArcGIS.ADF.Web.DataSources.IQueryFunctionality)

            ' Create a query filter.  If the field name is specified, use it as the filter's sub-field. If 
            ' the query expression is specified, use it as the filter's where clause.
            Dim adfQueryFilter As New ESRI.ArcGIS.ADF.Web.QueryFilter()
            adfQueryFilter.ReturnADFGeometries = False
            If fieldName IsNot Nothing Then
                adfQueryFilter.SubFields = New ESRI.ArcGIS.ADF.StringCollection(fieldName, ","c)
            End If
            If queryExpression IsNot Nothing Then
                adfQueryFilter.WhereClause = queryExpression
            End If

            ' Get the map resource's map functionality
            Dim commonMapFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality = Me.MapControl.GetFunctionality(commonMapResource)

            ' Execute the query, returning the result to the method caller
            Return commonQueryFunctionality.Query(commonMapFunctionality.Name, layerID, adfQueryFilter)
        End Function

#Region "UI Creation Methods"

        ' Creates an HTML table containing a label, drop-down list, and div containing activity
        ' indicators
        Private Function CreateDropDownListSection(ByRef dropDownList As System.Web.UI.HtmlControls.HtmlGenericControl, ByRef activityDiv As System.Web.UI.HtmlControls.HtmlGenericControl, ByVal dropDownLabelText As String, ByVal activityText As String) As System.Web.UI.WebControls.Table
            ' Use the method overload to create the table and add the label and drop-down list
            Dim table As System.Web.UI.WebControls.Table = Me.CreateDropDownListSection(dropDownList, dropDownLabelText)

            ' Call the method that will create a div with an activity indicator and label
            activityDiv = Me.CreateActivityDiv(activityText)

            ' Get the table cell containing the drop-down list and add the activity div to it
            Dim tableCell As System.Web.UI.WebControls.TableCell = table.Rows(0).Cells(1)
            tableCell.Controls.Add(activityDiv)

            Return table
        End Function

        ' Creates an HTML table containing a label and drop-down list
        Private Function CreateDropDownListSection(ByRef dropDownList As System.Web.UI.HtmlControls.HtmlGenericControl, ByVal dropDownLabelText As String) As System.Web.UI.WebControls.Table
            ' Instantiate an HTML table and add it to the task's controls collection
            Dim table As New System.Web.UI.WebControls.Table()
            table.HorizontalAlign = System.Web.UI.WebControls.HorizontalAlign.Center
            Me.Controls.Add(table)

            ' Create a table row to hold the controls
            Dim tableRow As New System.Web.UI.WebControls.TableRow()
            table.Rows.Add(tableRow)

            ' Create a table cell to hold the label
            Dim tableCell As New System.Web.UI.WebControls.TableCell()
            tableRow.Cells.Add(tableCell)

            ' Create a label, assign it the passed-in text, and add it to the table cell
            Dim label As New System.Web.UI.WebControls.Label()
            label.Text = dropDownLabelText
            tableCell.Controls.Add(label)

            ' Create a table cell to hold the drop-down list
            tableCell = New System.Web.UI.WebControls.TableCell()
            tableRow.Cells.Add(tableCell)

            ' Instantiate the drop-down list and add it to the table cell
            dropDownList = New System.Web.UI.HtmlControls.HtmlGenericControl("select")
            tableCell.Controls.Add(dropDownList)

            Return table
        End Function

        ' Returns a div containing an activity indictor with the passed-in text
        Private Function CreateActivityDiv(ByVal activityText As String) As System.Web.UI.HtmlControls.HtmlGenericControl
            ' Initialize a div to hold the activity indicator.  Specify that the div be hidden and that
            ' its contents are always on the same line.
            Dim containerDiv As New System.Web.UI.HtmlControls.HtmlGenericControl("div")
            containerDiv.Style(System.Web.UI.HtmlTextWriterStyle.Display) = "none"
            containerDiv.Style(System.Web.UI.HtmlTextWriterStyle.WhiteSpace) = "nowrap"

            ' Initialize an image with an activity indicator and add it to the div
            Dim activityImage As New System.Web.UI.WebControls.Image()
            activityImage.ImageUrl = Me.Page.ClientScript.GetWebResourceUrl(GetType(SimpleScriptTask), "ESRI.ADF.Samples.CustomTasks.images.activity_indicator.gif")
            containerDiv.Controls.Add(activityImage)

            ' Initialize a label to display along with the activity indicator image and add it to the div
            Dim activityLabel As New System.Web.UI.WebControls.Label()
            activityLabel.Text = activityText
            containerDiv.Controls.Add(activityLabel)

            Return containerDiv
        End Function

        ' Creates an HTML table containing the Add to Query button and adds it to the task's 
        ' controls collection
        Private Sub CreateAddToQueryButtonSection()
            ' Create an HTML table to hold the Add to Query button
            Dim addToQueryButtonTable As New System.Web.UI.WebControls.Table()
            addToQueryButtonTable.HorizontalAlign = System.Web.UI.WebControls.HorizontalAlign.Center
            Me.Controls.Add(addToQueryButtonTable)

            ' Create a row and cell to hold the button
            Dim tableRow As New System.Web.UI.WebControls.TableRow()
            addToQueryButtonTable.Rows.Add(tableRow)

            Dim tableCell As New System.Web.UI.WebControls.TableCell()
            tableRow.Cells.Add(tableCell)

            ' Instantiate the button, specify its text, and add it to the table cell
            _addToQueryButton = New System.Web.UI.HtmlControls.HtmlInputButton()
            _addToQueryButton.Value = "Add to Query"
            tableCell.Controls.Add(_addToQueryButton)
        End Sub

        ' Creates an HTML table containing a horizontal rule and adds it to the task's controls
        ' collection
        Private Sub CreateSeparator()
            ' Create a table to hold the horizontal rule, specifying a width of 80%
            Dim separatorTable As New System.Web.UI.WebControls.Table()
            separatorTable.HorizontalAlign = System.Web.UI.WebControls.HorizontalAlign.Center
            Dim unit As New System.Web.UI.WebControls.Unit(80, System.Web.UI.WebControls.UnitType.Percentage)
            separatorTable.Width = unit
            Me.Controls.Add(separatorTable)

            ' Create a row and cell to contain the rule
            Dim tableRow As New System.Web.UI.WebControls.TableRow()
            separatorTable.Rows.Add(tableRow)

            Dim tableCell As New System.Web.UI.WebControls.TableCell()
            tableRow.Cells.Add(tableCell)

            ' Instantiate a horizontal rule and add it to the cell
            Dim horizontalRule As New System.Web.UI.HtmlControls.HtmlGenericControl("hr")
            tableCell.Controls.Add(horizontalRule)
        End Sub

        ' Creates an HTML table containing the operator buttons and adds it to the task's 
        ' controls collection
        Private Sub CreateOperatorButtonsSection()
            ' Instantiate a table to hold the first row of operator buttons
            Dim operatorButtonTable As New System.Web.UI.WebControls.Table()
            operatorButtonTable.HorizontalAlign = System.Web.UI.WebControls.HorizontalAlign.Center
            Me.Controls.Add(operatorButtonTable)

            Dim tableRow As New System.Web.UI.WebControls.TableRow()
            operatorButtonTable.Rows.Add(tableRow)

            ' Create a cell to hold the left parenthesis button
            Dim tableCell As New System.Web.UI.WebControls.TableCell()
            tableRow.Cells.Add(tableCell)

            ' Instantiate the left parenthesis button, assign its text, and add it to the cell
            _leftParenthesisButton = New System.Web.UI.HtmlControls.HtmlInputButton()
            _leftParenthesisButton.Value = "("
            tableCell.Controls.Add(_leftParenthesisButton)

            ' Create a cell to hold the right parenthesis button
            tableCell = New System.Web.UI.WebControls.TableCell()
            tableRow.Cells.Add(tableCell)

            ' Instantiate the right parenthesis button, assign its text, and add it to the cell
            _rightParenthesisButton = New System.Web.UI.HtmlControls.HtmlInputButton()
            _rightParenthesisButton.Value = ")"
            tableCell.Controls.Add(_rightParenthesisButton)

            ' Create a cell to hold the percent button
            tableCell = New System.Web.UI.WebControls.TableCell()
            tableRow.Cells.Add(tableCell)

            ' Instantiate the percent button, assign its text, and add it to the cell
            _percentButton = New System.Web.UI.HtmlControls.HtmlInputButton()
            _percentButton.Value = "%"
            tableCell.Controls.Add(_percentButton)

            ' Create a cell to thold the underscore button
            tableCell = New System.Web.UI.WebControls.TableCell()
            tableRow.Cells.Add(tableCell)

            ' Instantiate the underscore button, assign its text, and add it to the cell
            _underscoreButton = New System.Web.UI.HtmlControls.HtmlInputButton()
            _underscoreButton.Value = "_"
            tableCell.Controls.Add(_underscoreButton)

            ' Create a new table to hold the And, Or, and Not buttons
            operatorButtonTable = New System.Web.UI.WebControls.Table()
            operatorButtonTable.HorizontalAlign = System.Web.UI.WebControls.HorizontalAlign.Center
            Me.Controls.Add(operatorButtonTable)

            tableRow = New System.Web.UI.WebControls.TableRow()
            operatorButtonTable.Rows.Add(tableRow)

            ' Create a cell to hold the And button
            tableCell = New System.Web.UI.WebControls.TableCell()
            tableRow.Cells.Add(tableCell)

            ' Instantiate the And button, assign its text, and add it to the cell
            _andButton = New System.Web.UI.HtmlControls.HtmlInputButton()
            _andButton.Value = "And"
            tableCell.Controls.Add(_andButton)

            ' Create a cell to hold the Or button
            tableCell = New System.Web.UI.WebControls.TableCell()
            tableRow.Cells.Add(tableCell)

            ' Instantiate the Or button, assign its text, and add it to the cell
            _orButton = New System.Web.UI.HtmlControls.HtmlInputButton()
            _orButton.Value = "Or"
            tableCell.Controls.Add(_orButton)

            ' Create a cell to hold the Not button
            tableCell = New System.Web.UI.WebControls.TableCell()
            tableRow.Cells.Add(tableCell)

            ' Instantiate the Not button, assign its text, and add it to the cell
            _notButton = New System.Web.UI.HtmlControls.HtmlInputButton()
            _notButton.Value = "Not"
            tableCell.Controls.Add(_notButton)
        End Sub

        ' Creates an HTML table containing the query textbox and label and adds it to the 
        ' task's controls collection
        Private Sub CreateQuerySection()
            ' Creaet a table to hold the query label and textbox, specifying a width of 95%
            Dim queryTable As New System.Web.UI.WebControls.Table()
            queryTable.HorizontalAlign = System.Web.UI.WebControls.HorizontalAlign.Center
            Dim unit As New System.Web.UI.WebControls.Unit(95, System.Web.UI.WebControls.UnitType.Percentage)
            queryTable.Width = unit
            Me.Controls.Add(queryTable)

            ' Create a row and cell to hold the query textbox label
            Dim tableRow As New System.Web.UI.WebControls.TableRow()
            queryTable.Rows.Add(tableRow)
            Dim tableCell As New System.Web.UI.WebControls.TableCell()
            tableRow.Cells.Add(tableCell)

            ' Instantiate the query textbox label, assign its text, and add it to the cell
            Dim queryLabel As New System.Web.UI.WebControls.Label()
            queryLabel.Text = "Query:"
            tableCell.Controls.Add(queryLabel)

            ' Create a row and cell to hold the query textbox
            tableRow = New System.Web.UI.WebControls.TableRow()
            queryTable.Rows.Add(tableRow)
            tableCell = New System.Web.UI.WebControls.TableCell()
            tableRow.Cells.Add(tableCell)

            ' Instantiate the query textbox.  Specify multi-line capability, word wrapping, and a 
            ' height of 80 pixels.  Then add it to its container cell.
            _queryTextBox = New System.Web.UI.WebControls.TextBox()
            _queryTextBox.TextMode = System.Web.UI.WebControls.TextBoxMode.MultiLine
            _queryTextBox.Wrap = True
            _queryTextBox.Height = CType(80, System.Web.UI.WebControls.Unit)
            _queryTextBox.Width = unit

            tableCell.Controls.Add(_queryTextBox)
        End Sub

        ' Creates an HTML table containing the Clear Query and Execute Query buttons and adds
        ' it to the task's controls collection
        Private Sub CreateQueryButtonsSection()
            ' Create a table to hold the Clear Query and Execute Query buttons
            Dim queryButtonTable As New System.Web.UI.WebControls.Table()
            queryButtonTable.HorizontalAlign = System.Web.UI.WebControls.HorizontalAlign.Center
            Me.Controls.Add(queryButtonTable)

            Dim tableRow As New System.Web.UI.WebControls.TableRow()
            queryButtonTable.Rows.Add(tableRow)

            ' Create a table cell to hold the Clear Query button
            Dim tableCell As New System.Web.UI.WebControls.TableCell()
            tableRow.Cells.Add(tableCell)

            ' Instantiate the Clear Query button, specify its text, and add it to its container cell
            _clearQueryButton = New System.Web.UI.HtmlControls.HtmlInputButton()
            _clearQueryButton.Value = "Clear Query"
            tableCell.Controls.Add(_clearQueryButton)

            ' Create a cell to hold the Execute Query button
            tableCell = New System.Web.UI.WebControls.TableCell()
            tableRow.Cells.Add(tableCell)

            ' Instantiate the Execute Query button, specify its text, and add it to its container cell
            _doQueryButton = New System.Web.UI.HtmlControls.HtmlInputButton()
            _doQueryButton.Value = "Execute Query"
            tableCell.Controls.Add(_doQueryButton)

            ' Call method to create the query execution activity indicator div and add it to the same
            ' cell as the Execute Query button
            _executingQueryDiv = Me.CreateActivityDiv("Executing Query...")
            tableCell.Controls.Add(_executingQueryDiv)
        End Sub

#End Region

#End Region

#End Region

#Region "Instance Properties"

#Region "Public Properties"

        ' Specifies that the property will appear in Visual Studio's properties pane
        ' Specifies the category within which the property will be grouped
        ' Specifies the property's default value
        ' Stores the ID of the map to which the task is buddied
        <System.ComponentModel.Browsable(True), System.ComponentModel.Category("BuddyControls"), System.ComponentModel.DefaultValue("Map1")> _
        Public Property Map() As String
            Get
                ' Attempt to retrieve the Map ID from state
                Dim mapID As String = TryCast(StateManager.GetProperty("MapID"), String)
                ' If no Map ID was stored in state, return the default value.  Otherwise,
                ' return the stroed value.
                Return If((mapID Is Nothing), "Map1", mapID)
            End Get
            Set(ByVal value As String)
                ' Store the passed-in value in state
                StateManager.SetProperty("MapID", value)
            End Set
        End Property

        ' Specifies that the property will appear in Visual Studio's properties pane
        ' Specifies the category within which the property will be grouped
        ' Specifies the property's default value
        ' Indicates whether queryable layers belonging to graphics resources should be included for 
        ' querying by the task
        <System.ComponentModel.Browsable(True), System.ComponentModel.Category("Task"), System.ComponentModel.DefaultValue("True")> _
        Public Property ExcludeGraphicsResources() As Boolean
            Get
                ' If the property has not been stored in state, return true.  Otherwise, return the stored
                ' value.
                'INSTANT VB NOTE: The local variable excludeGraphicsResources was renamed since Visual Basic will not allow local variables with the same name as their enclosing function or property:
                Dim excludeGraphicsResources_Renamed As Boolean = True
                If StateManager.GetProperty("ExcludeGraphicsResources") IsNot Nothing Then
                    excludeGraphicsResources_Renamed = CBool(StateManager.GetProperty("ExcludeGraphicsResources"))
                End If
                Return excludeGraphicsResources_Renamed
            End Get
            Set(ByVal value As Boolean)
                ' Store the passed-in value in state
                StateManager.SetProperty("ExcludeGraphicsResources", value)
            End Set
        End Property

#End Region

        ' Provides easy access to the ADF Map control referred to by the ID stored in the task's 
        ' Map property
        Private ReadOnly Property MapControl() As ESRI.ArcGIS.ADF.Web.UI.WebControls.Map
            Get
                ' Retrieve the map control specified by the task's Map property.  Note that this
                ' is retrieved dynamically whenever the property is called so that the correct
                ' map is always returned (i.e. even after changing the Map property).
                Dim adfMap As ESRI.ArcGIS.ADF.Web.UI.WebControls.Map = TryCast(ESRI.ArcGIS.ADF.Web.UI.WebControls.Utility.FindControl(Me.Map, Me.Page), ESRI.ArcGIS.ADF.Web.UI.WebControls.Map)
                Return adfMap
            End Get
        End Property

#End Region
    End Class
End Namespace