Common_CustomEditorTask_VBNet\CustomEditorTask_VBNet\QueryBuilderPanel.vb
' Copyright 2011 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 CustomEditorTask_VBNet <AjaxControlToolkit.ClientScriptResource("CustomEditorTask_VBNet.QueryBuilderPanel", "QueryBuilderPanel.js")> _ Friend Class QueryBuilderPanel Inherits ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditorPanel #Region "Instance Variable Declarations" Private m_lblFields As System.Web.UI.WebControls.Label Private m_ddFields As System.Web.UI.WebControls.DropDownList Private m_lblOperator As System.Web.UI.WebControls.Label Private m_ddOperators As System.Web.UI.WebControls.DropDownList Private m_lblValues As System.Web.UI.WebControls.Label Private m_ddValues As System.Web.UI.WebControls.DropDownList Private m_btnAddToQuery As System.Web.UI.WebControls.Button Private m_btnAnd As System.Web.UI.WebControls.Button Private m_btnOr As System.Web.UI.WebControls.Button Private m_btnNot As System.Web.UI.WebControls.Button Private m_btnLtPara As System.Web.UI.WebControls.Button Private m_btnRtPara As System.Web.UI.WebControls.Button Private m_btnPct As System.Web.UI.WebControls.Button Private m_btnUnderscore As System.Web.UI.WebControls.Button Private m_txtQuery As System.Web.UI.WebControls.TextBox Private m_btnClearQuery As System.Web.UI.WebControls.Button Private m_btnDoQuery As System.Web.UI.WebControls.Button #End Region #Region "Constructor" Public Sub New(ByVal editorTask As ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditorTask) MyBase.New("Query Builder", editorTask, "queryBuilderPanel") AddHandler ParentEditor.LayerChanged, AddressOf ParentEditor_LayerChanged End Sub #End Region #Region "WebControl Life Cycle Event Overrides" Protected Overrides Sub OnInit(ByVal eventArgs As System.EventArgs) MyBase.OnInit(eventArgs) ' Set height to limit the amount of screen space occupied by the panel Me.Height = System.Web.UI.WebControls.Unit.Pixel(200) End Sub ' Instantiate the panel's child controls Protected Overrides Sub CreateChildControls() MyBase.CreateChildControls() ' Instantiate panel controls and add them to the custom panel's controls collection ' Label for the Fields drop-down m_lblFields = New System.Web.UI.WebControls.Label() m_lblFields.ID = "lblFields" m_lblFields.Text = "Fields:" Controls.Add(m_lblFields) ' Fields drop-down m_ddFields = New System.Web.UI.WebControls.DropDownList() m_ddFields.ID = "ddFields" ' Initialization of items in the fields drop-down. Necessary include logic for doing this here ' in case only one version is available for editing. In that case, the controls will not be ' instantiated before the layer changed event fires Dim fieldsInit As Boolean = False If CustomEditorInstance.FeatureLayer IsNot Nothing Then ' Get fields and add to fields drop-down Dim fields As String = CustomUtilities.GetFields(CustomEditorInstance) Dim delimiter() As Char = {":"c} Dim fieldList() As String = fields.Split(delimiter, System.StringSplitOptions.RemoveEmptyEntries) For i As Integer = 0 To fieldList.Length - 1 m_ddFields.Items.Add(fieldList(i)) Next i fieldsInit = True End If Controls.Add(m_ddFields) ' Label for operator drop-down m_lblOperator = New System.Web.UI.WebControls.Label() m_lblOperator.ID = "lblOperator" m_lblOperator.Text = "Operators:" Controls.Add(m_lblOperator) ' Operator drop-down initialization m_ddOperators = New System.Web.UI.WebControls.DropDownList() m_ddOperators.ID = "ddOperators" m_ddOperators.Items.Add("=") m_ddOperators.Items.Add(">") m_ddOperators.Items.Add("<") m_ddOperators.Items.Add(">=") m_ddOperators.Items.Add("<=") m_ddOperators.Items.Add("LIKE") Controls.Add(m_ddOperators) ' Label for sample values drop-down m_lblValues = New System.Web.UI.WebControls.Label() m_lblValues.ID = "lblValues" m_lblValues.Text = "Sample Values:" Controls.Add(m_lblValues) ' Sample values drop-down initialization m_ddValues = New System.Web.UI.WebControls.DropDownList() m_ddValues.ID = "ddValues" If fieldsInit Then 'get sample values and add to sample values drop-down Dim samples As String = CustomUtilities.GetSampleValues(m_ddFields.Items(m_ddFields.SelectedIndex).Text, Me.ParentEditor) Dim delimiter() As Char = {":"c} Dim sampleList() As String = samples.Split(delimiter, System.StringSplitOptions.RemoveEmptyEntries) Dim nvcSampleList As New System.Collections.Specialized.NameValueCollection() System.Array.Sort(sampleList) For i As Integer = 0 To sampleList.Length - 1 m_ddValues.Items.Add(sampleList(i)) Next i End If Controls.Add(m_ddValues) ' Add to query button m_btnAddToQuery = New System.Web.UI.WebControls.Button() m_btnAddToQuery.ID = "btnAddToQuery" m_btnAddToQuery.Text = "Add to Query" Controls.Add(m_btnAddToQuery) ' Left parentheses button m_btnLtPara = New System.Web.UI.WebControls.Button() m_btnLtPara.ID = "btnLtPara" m_btnLtPara.Text = "(" Controls.Add(m_btnLtPara) ' Right parentheses button m_btnRtPara = New System.Web.UI.WebControls.Button() m_btnRtPara.ID = "btnRtPara" m_btnRtPara.Text = ")" Controls.Add(m_btnRtPara) ' Percent button m_btnPct = New System.Web.UI.WebControls.Button() m_btnPct.ID = "btnPct" m_btnPct.Text = "%" Controls.Add(m_btnPct) ' Underscore button m_btnUnderscore = New System.Web.UI.WebControls.Button() m_btnUnderscore.ID = "btnUnderscore" m_btnUnderscore.Text = "_" Controls.Add(m_btnUnderscore) ' AND button m_btnAnd = New System.Web.UI.WebControls.Button() m_btnAnd.ID = "btnAnd" m_btnAnd.Text = " AND " Controls.Add(m_btnAnd) ' OR button m_btnOr = New System.Web.UI.WebControls.Button() m_btnOr.ID = "btnOr" m_btnOr.Text = " OR " Controls.Add(m_btnOr) ' NOT button m_btnNot = New System.Web.UI.WebControls.Button() m_btnNot.ID = "btnNot" m_btnNot.Text = " NOT " Controls.Add(m_btnNot) ' Query textbox m_txtQuery = New System.Web.UI.WebControls.TextBox() m_txtQuery.ID = "txtQuery" m_txtQuery.TextMode = System.Web.UI.WebControls.TextBoxMode.MultiLine m_txtQuery.Wrap = True m_txtQuery.Height = CType(80, System.Web.UI.WebControls.Unit) Controls.Add(m_txtQuery) ' Clear query button m_btnClearQuery = New System.Web.UI.WebControls.Button() m_btnClearQuery.ID = "btnClearQuery" m_btnClearQuery.Text = "Clear" Controls.Add(m_btnClearQuery) ' Execute query button m_btnDoQuery = New System.Web.UI.WebControls.Button() m_btnDoQuery.ID = "btnDoQuery" m_btnDoQuery.Text = "Execute" Controls.Add(m_btnDoQuery) End Sub Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs) MyBase.OnPreRender(e) ' Register the JavaScript file containing client-side functions used by the panel 'System.Web.UI.ScriptManager.RegisterClientScriptResource((System.Web.UI.Control)this, this.GetType(), ' "CustomEditorTask_CSharp.javascript.QueryBuilderPanel.js"); ' Initialize the OIDFieldName property Me.OIDfieldName = CustomEditorInstance.FeatureLayer.FeatureClass.OIDFieldName End Sub ' Render the panel's child controls Protected Overrides Sub RenderContents(ByVal writer As System.Web.UI.HtmlTextWriter) If ParentEditor.MapResource Is Nothing Then Return End If ' ==Format the layout of controls on the panel and wire necessary JavaScript ' Render a table to contain the panel's controls writer.AddAttribute(System.Web.UI.HtmlTextWriterAttribute.Cellpadding, "3px") writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.OverflowY, "auto") writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.Width, "90%") writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Table) ' Fields label and drop-down writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.WhiteSpace, "nowrap") writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Tr) writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Td) m_lblFields.RenderControl(writer) writer.Write(" ") ' Link a JavaScript call to getValues to the onchange event of the Fields drop-down. this will call ' getValues when the user selects a new field. Dim jsOnChange As String = System.String.Format("javascript:getValues('{0}','{1}','{2}')", m_ddFields.ClientID, m_ddValues.ClientID, Me.CallbackFunctionString.Replace("'", "\'")) m_ddFields.Attributes.Add("onchange", jsOnChange) m_ddFields.RenderControl(writer) writer.RenderEndTag() 'td writer.RenderEndTag() 'tr ' Operator label and drop-down writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.WhiteSpace, "nowrap") writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Tr) writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Td) m_lblOperator.RenderControl(writer) writer.Write(" ") m_ddOperators.RenderControl(writer) writer.RenderEndTag() 'td writer.RenderEndTag() 'tr ' Values label and drop-down writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.WhiteSpace, "nowrap") writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Tr) writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Td) m_lblValues.RenderControl(writer) writer.Write(" ") m_ddValues.RenderControl(writer) writer.RenderEndTag() 'td writer.RenderEndTag() ' tr ' Add to query button writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.TextAlign, "center") writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Tr) writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Td) ' link JavaScript call to addToQuery to the onclick event. m_btnAddToQuery.OnClientClick = String.Format("addToQuery('{0}', '{1}', '{2}', '{3}')", m_ddFields.ClientID, m_ddOperators.ClientID, m_ddValues.ClientID, m_txtQuery.ClientID) m_btnAddToQuery.RenderControl(writer) writer.RenderEndTag() ' td writer.RenderEndTag() ' tr ' hr to separate sections of panel writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.TextAlign, "center") writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Tr) writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Td) writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.Width, "80%") writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Hr) writer.RenderEndTag() 'hr writer.RenderEndTag() 'td writer.RenderEndTag() ' tr ' Parentheses, percent, and underscore buttons writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.WhiteSpace, "nowrap") writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.TextAlign, "center") writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Tr) writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Td) ' Format JavaScript to add the text of the button clicked to query. Dim onclick As String = String.Format("var txt = document.getElementById('{0}');" & "txt.innerHTML += this.value; txt.focus();", m_txtQuery.ClientID) m_btnLtPara.OnClientClick = onclick m_btnLtPara.RenderControl(writer) writer.Write(" ") m_btnRtPara.OnClientClick = onclick m_btnRtPara.RenderControl(writer) writer.Write(" ") m_btnPct.OnClientClick = onclick m_btnPct.RenderControl(writer) writer.Write(" ") m_btnUnderscore.OnClientClick = onclick m_btnUnderscore.RenderControl(writer) writer.Write(" ") writer.RenderEndTag() ' td writer.RenderEndTag() ' tr 'AND, OR, and NOT buttons writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.WhiteSpace, "nowrap") writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.TextAlign, "center") writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Tr) writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Td) m_btnAnd.OnClientClick = onclick m_btnAnd.RenderControl(writer) writer.Write(" ") m_btnOr.OnClientClick = onclick m_btnOr.RenderControl(writer) writer.Write(" ") m_btnNot.OnClientClick = onclick m_btnNot.RenderControl(writer) writer.RenderEndTag() 'td writer.RenderEndTag() ' tr ' hr to separate sections of panel writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.TextAlign, "center") writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Tr) writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Td) writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.Width, "80%") writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Hr) writer.RenderEndTag() 'hr writer.RenderEndTag() 'td writer.RenderEndTag() ' tr ' Query textbox writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.TextAlign, "center") writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Tr) writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Td) writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.Width, "100%") m_txtQuery.RenderControl(writer) writer.RenderEndTag() ' td writer.RenderEndTag() ' tr ' Clear Query and Execute buttons writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.WhiteSpace, "nowrap") writer.AddStyleAttribute(System.Web.UI.HtmlTextWriterStyle.TextAlign, "center") writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Tr) writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Td) ' Link JavaScript to clear query text to fire when the Clear Query button is clicked. m_btnClearQuery.OnClientClick = String.Format("document.getElementById('{0}').innerHTML = ''", m_txtQuery.ClientID) m_btnClearQuery.RenderControl(writer) writer.Write(" ") ' Link JavaScript call to doQuery to fire when Execute button is clicked. m_btnDoQuery.OnClientClick = String.Format("doQuery('{0}','{1}')", m_txtQuery.ClientID, Me.CallbackFunctionString.Replace("'", "\'")) m_btnDoQuery.RenderControl(writer) writer.RenderEndTag() ' td writer.RenderEndTag() ' tr writer.RenderEndTag() ' table End Sub #End Region #Region "Web ADF Event Handlers" Private Sub ParentEditor_LayerChanged(ByVal featureLayer As ESRI.ArcGIS.Carto.IFeatureLayer) If m_ddFields IsNot Nothing Then ' Get object ID field Me.OIDfieldName = featureLayer.FeatureClass.OIDFieldName Dim fieldList As String = CustomUtilities.GetFields(CustomEditorInstance) ' Format JavaScript to populate the fields drop-down list and add to callback results Dim jsPopulateFieldsDropDown As String = String.Format("populateDropDown('{0}', '{1}');", m_ddFields.ClientID, fieldList) Dim populateFieldsCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsPopulateFieldsDropDown) Me.ParentEditor.CallbackResults.Add(populateFieldsCallbackResult) ' Put the fields contained in the fieldList string into a string array Dim separator() As Char = {":"c} Dim fieldsArray() As String = fieldList.Split(separator, System.StringSplitOptions.RemoveEmptyEntries) ' Get list of sample values for the first field in the fields list Dim sampleValueList As String = CustomUtilities.GetSampleValues(fieldsArray(0), Me.ParentEditor) ' Construct JavaScript call to populateDropDown to populate sample values based on the field selected Dim jsPopulateSampleValuesDropDown As String = String.Format("populateDropDown('{0}', '{1}', '{2}');", m_ddValues.ClientID, sampleValueList, "true") ' Create new callback result from JavaScript call and add to callback results Dim populateSampleValuesCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsPopulateSampleValuesDropDown) Me.ParentEditor.CallbackResults.Add(populateSampleValuesCallbackResult) ' Format JavaScript to clear the query textbox and add to callback results Dim jsClearQueryTextbox As String = String.Format("document.getElementById('{0}').innerHTML = ''", m_txtQuery.ClientID) Dim clearQueryCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsClearQueryTextbox) Me.ParentEditor.CallbackResults.Add(clearQueryCallbackResult) End If End Sub #End Region '; #Region "Callback Handler" Public Overrides Function GetCallbackResult() As String ' Replace HTML reserved character codes in the callback argument Dim callbackArgument As String = Me.CallbackEventArgument.Replace(">", ">") callbackArgument = callbackArgument.Replace("<", "<") ' Parse callback arguments using the CallbackUtility included with Web ADF. ' The CallbackEventArgument is a member variable inherited from ' ESRI.ArcGIS.ADF.Web.UI.WebControls.CompositeControl. During a callback, it ' contains the string argument passed to RaiseCallbackEvent(). Dim nvcCallbackArgs As System.Collections.Specialized.NameValueCollection = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection(callbackArgument) ' Get value of EventArg Dim eventArg As String = nvcCallbackArgs("EventArg") ' Check eventArg and take action accordingly If eventArg = "fieldSelected" Then ' Get list of sample values Dim sampleValuesList As String = CustomUtilities.GetSampleValues(nvcCallbackArgs("field"), Me.ParentEditor) ' Construct JavaScript call to populateDropDown to populate sample values based on field selected Dim jsPopulateSampleValuesDropDown As String = String.Format("populateDropDown('{0}', '{1}', '{2}');", m_ddValues.ClientID, sampleValuesList, "true") ' Create new callback result with JavaScript call and add to collection Dim populateSampleValuesCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsPopulateSampleValuesDropDown) Me.CallbackResults.Add(populateSampleValuesCallbackResult) 'return callback results Return Me.CallbackResults.ToString() ElseIf eventArg = "doQuery" Then ' Replace aliases in query string with actual database field names Dim query As String = Me.ReplaceAliases(nvcCallbackArgs("query")) ' Exit without returning results if query is null If query Is Nothing Then Return Nothing End If ' Get IDs of features satisfying query Dim ids() As Integer = CustomUtilities.DoQuery(query, Me.ParentEditor) ' Get LayerDescription object for currently selected layer Dim adfLayerDescription As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription = ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditorUtilities.GetLayerDescription(Me.ParentEditor.MapFunctionality, Me.ParentEditor.SelectedLayerID) Dim selectionChanged As Boolean Dim selectedIDsArray As System.Collections.Generic.List(Of Integer) = CustomUtilities.UpdateSelection(adfLayerDescription.SelectionFeatures, ids, selectionChanged, Me.ParentEditor.EditorTask) ' Exit function without returning callback results if selection is unchanged If (Not selectionChanged) Then Return Nothing End If ' Set selected features on layer currently being edited adfLayerDescription.SelectionFeatures = selectedIDsArray.ToArray() ' Get attributes panel and set to edit the attributes of selected features Dim editAttributesPanel As ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditAttributesPanel = CType(Me.ParentEditor.AttributesEditor, ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditAttributesPanel) Dim editAttributesPanelCallbackResultsCollection As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResultCollection = editAttributesPanel.SetSelectedFeatures(adfLayerDescription.SelectionFeatures) Me.CallbackResults.CopyFrom(editAttributesPanelCallbackResultsCollection) ' Refresh map ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditorUtilities.RefreshMap(Me.ParentEditor, Me.CallbackResults) Me.CallbackResults.CopyFrom(Me.ParentEditor.Map.CallbackResults) ' Refresh toolbars Me.ParentEditor.RefreshToolbars(Me.CallbackResults) ' Create callback result that calls JavaScript to hide AJAX activity indicator Dim jsHideIndicator As String = String.Format("showEditorElement(false,'{0}');", "ajaxActivityID") Dim hideActivityIndicatorCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsHideIndicator) Me.CallbackResults.Add(hideActivityIndicatorCallbackResult) ' Return callback results Return Me.CallbackResults.ToString() Else Return MyBase.GetCallbackResult() End If End Function #End Region #Region "Instance Properties" ' Name of object ID field of selected layer Protected Property OIDfieldName() As String Get Return CStr(StateManager.GetProperty("selectedLayerOIDfield")) End Get Set(ByVal value As String) StateManager.SetProperty("selectedLayerOIDfield", value) End Set End Property ' Easy access to the CustomEditor containing the panel instance Protected ReadOnly Property CustomEditorInstance() As CustomEditor Get Return CType(Me.ParentEditor, CustomEditor) End Get End Property #End Region #Region "Instance Methods" ' Replace field aliases in passed-in string with corresponding actual database field names Private Function ReplaceAliases(ByVal query As String) As String ' Rebuild query string, replacing aliases with database field names Dim newQuery As String = query.Substring(0, query.IndexOf("[")) query = query.Substring(query.IndexOf("[")) Dim [alias] As String = Nothing Dim field As String = Nothing Do ' Get alias from query string [alias] = query.Substring(1, query.IndexOf("]") - 1) ' Get database field name of alias field = CustomUtilities.GetFieldName([alias], CustomEditorInstance) If field Is Nothing Then Return Nothing End If query = query.Substring(query.IndexOf("]") + 1) If query.IndexOf("[") > -1 Then newQuery &= field & query.Substring(0, query.IndexOf("[")) query = query.Substring(query.IndexOf("[")) Else newQuery &= field & query End If Loop While query.IndexOf("]") > -1 Return newQuery End Function #End Region End Class End Namespace