Common_CustomEditorTask_VBNet\CustomEditorTask_VBNet\SearchAttributesPanel.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 CustomEditorTask_VBNet <AjaxControlToolkit.ClientScriptResource("CustomEditorTask_VBNet.SearchAttributesPanel", "SearchAttributesPanel.js")> _ Friend Class SearchAttributesPanel Inherits ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditorPanel #Region "Instance Variable Declarations" Private m_panelDiv As System.Web.UI.HtmlControls.HtmlGenericControl Private m_callbackArgsCollection As System.Collections.Specialized.NameValueCollection #End Region #Region "Constructor" Public Sub New(ByVal editorTask As ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditorTask) MyBase.New("Search", editorTask, "searchAttributesPanel") ' Add a handler that fires when a new editor layer is selected AddHandler ParentEditor.LayerChanged, AddressOf ParentEditor_LayerChanged End Sub #End Region #Region "WebControl Life Cycle Event Overrides" Protected Overrides Sub CreateChildControls() MyBase.CreateChildControls() ' Create a container div for the client-side UI component m_panelDiv = New System.Web.UI.HtmlControls.HtmlGenericControl("div") m_panelDiv.ID = "searchAttributesPanelDiv" Controls.Add(m_panelDiv) End Sub Protected Overrides Sub OnPreRender(ByVal e As System.EventArgs) MyBase.OnPreRender(e) ' Register the JavaScript file containing the SearchAttributesPanel JavaScript UI ' component and functions to control interaction between the client panel and the server 'System.Web.UI.ScriptManager.RegisterClientScriptResource((System.Web.UI.Control)this, ' this.GetType(), "CustomEditorTask_CSharp.javascript.SearchAttributesPanel.js"); 'this.Page.ClientScript.RegisterClientScriptResource(this.GetType(), "CustomEditorTask_CSharp.javascript.SearchAttributesPanel.js"); ' Get a reference to the editor task's layers drop-down list Dim editorLayerList As System.Web.UI.WebControls.DropDownList = Nothing editorLayerList = TryCast(CustomUtilities.FindControl("editTaskLayerList", TryCast(Me.ParentEditor, System.Web.UI.Control)), System.Web.UI.WebControls.DropDownList) ' Get strings containing the numeric and text fields for the current layer Dim numericFields As String = CustomUtilities.GetFields(CustomEditorInstance, CustomUtilities.FieldType.Numeric) Dim textFields As String = CustomUtilities.GetFields(CustomEditorInstance, CustomUtilities.FieldType.Text) ' Get the URL of the activity_indicator image file Dim activityIndicatorUrl As String = Me.Page.ClientScript.GetWebResourceUrl(GetType(CustomEditorTask), "CustomEditorTask_CSharp.images.activity_indicator.gif") Dim csname1 As String = Me.ClientID & "_init" If (Not Page.ClientScript.IsStartupScriptRegistered(Me.GetType(), csname1)) Then ' Construct the JavaScript necessary to initialize the client-side search panel with ' server-side properties Dim scriptBlock As String = " " & ControlChars.CrLf & " function invokeSearchPanelInitialization(){{" & ControlChars.CrLf & " initializeSearchPanel('{0}', '{1}', '{2}', '{3}', '{4}', ""{5}"");" & ControlChars.CrLf & " }}" & ControlChars.CrLf & " Sys.Application.add_init(invokeSearchPanelInitialization);" scriptBlock = String.Format(scriptBlock, m_panelDiv.ClientID, editorLayerList.ClientID, numericFields, textFields, activityIndicatorUrl, Me.CallbackFunctionString) ' Register the initialization code as a startup script Me.Page.ClientScript.RegisterStartupScript(Me.GetType(), Me.ClientID & "_init", scriptBlock, True) End If ' Initialize the OIDFieldName property Me.OIDfieldName = CustomEditorInstance.FeatureLayer.FeatureClass.OIDFieldName End Sub Protected Overrides Sub RenderContents(ByVal writer As System.Web.UI.HtmlTextWriter) MyBase.RenderContents(writer) ' Create a callback result that will call the renderSearchPanel JavaScript function, which ' will expicitly re-render the client-side search panel. This is necessary because the ' server has no knowledge of the client-side panel's elements, so when the panel is rendered ' (which is done with information stored in state on the server), these elements are lost. Dim renderSearchPanelCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript("renderSearchPanel();") Me.ParentEditor.CallbackResults.Add(renderSearchPanelCallbackResult) End Sub #End Region #Region "Web ADF Event Handlers" ' Fires when the user selects a different layer from the editor task's layers drop-down list Private Sub ParentEditor_LayerChanged(ByVal featureLayer As ESRI.ArcGIS.Carto.IFeatureLayer) ' Get the object ID field of the newly selected layer Me.OIDfieldName = featureLayer.FeatureClass.OIDFieldName ' Get the numeric and text fields of the new layer Dim numericFields As String = CustomUtilities.GetFields(CustomEditorInstance, CustomUtilities.FieldType.Numeric) Dim textFields As String = CustomUtilities.GetFields(CustomEditorInstance, CustomUtilities.FieldType.Text) ' Construct a call to a JavaScript function that will update the client-side search ' panel with the new layer's fields Dim jsUpdateFields As String = String.Format("updateSearchPanelFields('{0}', '{1}');", textFields, numericFields) Dim updateFieldsCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsUpdateFields) Me.ParentEditor.CallbackResults.Add(updateFieldsCallbackResult) End Sub #End Region '; #Region "Callback Handler" Public Overrides Sub RaiseCallbackEvent(ByVal eventArgs As String) ' Parse callback arguments using the CallbackUtility included with Web ADF. m_callbackArgsCollection = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection(eventArgs) ' Check whether the current event argument indicates that a search was initiated by the user If m_callbackArgsCollection("EventArg") = "search" Then ' Get the fields selected by the user, with aliases replaced by database field names Dim searchFieldsString As String = CustomUtilities.ReplaceAliases(m_callbackArgsCollection("Fields"), CustomEditorInstance) ' Parse the fields string into an array Dim delimiter() As Char = {";"c} Dim searchFieldsArray() As String = searchFieldsString.Split(delimiter, System.StringSplitOptions.RemoveEmptyEntries) ' Build a query string based on the selected fields, operator, and search value Dim queryString As String = Me.BuildQuery(m_callbackArgsCollection("Operator"), searchFieldsArray, m_callbackArgsCollection("Value")) ' Get IDs of features satisfying query Dim matchingFeatureIDs() As Integer = CustomUtilities.DoQuery(queryString, Me.ParentEditor) ' Get LayerDescription object for currently selected layer Dim agsLayerDescription As ESRI.ArcGIS.ADF.ArcGISServer.LayerDescription = ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditorUtilities.GetLayerDescription(Me.ParentEditor.MapFunctionality, Me.ParentEditor.SelectedLayerID) ' Combine the feature IDs from the query with those currently selected. How this ' is done will depend on the selection option currently specified in the editor ' task's settings Dim selectionChanged As Boolean Dim selectedIDsList As System.Collections.Generic.List(Of Integer) = CustomUtilities.UpdateSelection(agsLayerDescription.SelectionFeatures, matchingFeatureIDs, selectionChanged, Me.ParentEditor.EditorTask) ' Check whether the selected IDs changed If selectionChanged Then ' Set selected features on layer currently being edited agsLayerDescription.SelectionFeatures = selectedIDsList.ToArray() ' Get attributes panel and set to edit the attributes of selected features Dim editAttributesPanel As ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditAttributesPanel = TryCast(Me.ParentEditor.AttributesEditor, ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditAttributesPanel) Dim editAttributesPanelResults As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResultCollection = editAttributesPanel.SetSelectedFeatures(agsLayerDescription.SelectionFeatures) Me.CallbackResults.CopyFrom(editAttributesPanelResults) ' Refresh map ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditorUtilities.RefreshMap(Me.ParentEditor, Me.CallbackResults) ' Refresh toolbars Me.ParentEditor.RefreshToolbars(Me.CallbackResults) End If ' Create callback result that calls JavaScript to hide AJAX activity indicator Dim jsHideIndicator As String = "hideSearchingIndicator();" Dim hideIndicatorCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult.CreateJavaScript(jsHideIndicator) Me.CallbackResults.Add(hideIndicatorCallbackResult) Else MyBase.RaiseCallbackEvent(eventArgs) End If End Sub Public Overrides Function GetCallbackResult() As String ' If the callback was initiated by a search operation, return the panel's callback results If m_callbackArgsCollection("EventArg") = "search" Then 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" ' Builds a query string from search parameters Private Function BuildQuery(ByVal searchType As String, ByVal searchFields() As String, ByVal searchValue As String) As String Dim queryString As String = "" Dim searchWords() As String ' Check the specified search type Select Case searchType Case "All words" ' Parse the words contained in the search value and place them in an array. ' The Split method uses the space character as a default delimiter. searchWords = searchValue.Split() ' Since we only want to find features that contain all the words of the search ' value, we iterate through the search words and build the query to extract ' features that contain each word in any field. For i As Integer = 0 To searchWords.Length - 1 queryString &= "(" For j As Integer = 0 To searchFields.Length - 1 queryString &= String.Format("({0} LIKE '%{1}%')", searchFields(j), searchWords(i)) If j < searchFields.Length - 1 Then queryString &= " OR " End If Next j queryString &= ")" If i < searchWords.Length - 1 Then queryString &= " AND " End If Next i Case "Any words" ' Parse the words contained in the search value and place them in an array. ' The Split method uses the space character as a default delimiter. searchWords = searchValue.Split() ' Since we want to find features that contain any of the words of the search ' value, we iterate through the search words and build the query to extract ' features that contain any word in any field. For i As Integer = 0 To searchWords.Length - 1 For j As Integer = 0 To searchFields.Length - 1 queryString &= String.Format("({0} LIKE '%{1}%')", searchFields(j), searchWords(i)) If (j < searchFields.Length - 1) OrElse (i < searchWords.Length - 1) Then queryString &= " OR " End If Next j Next i Case "Exact phrase" ' Since we only want to find features that contain the entire search value as ' specified by the user, we iterate through the search fields and build the ' query to extract features that contain the whole search value in any field. For i As Integer = 0 To searchFields.Length - 1 queryString &= String.Format("({0} LIKE '%{1}%')", searchFields(i), searchValue) If i < searchFields.Length - 1 Then queryString &= " OR " End If Next i Case Else Dim queryOperator As String = Nothing ' For numeric operators, check the search type and initialize a variable ' storing the corresponding logical operator Select Case searchType Case "Equal to" queryOperator = "=" Case "Greater than" queryOperator = ">" Case "Less than" queryOperator = "<" End Select ' Iterate through the search fields and build a query to extract features ' that have at least one value satisfying the relationship to the search ' value specified by the query operator For i As Integer = 0 To searchFields.Length - 1 queryString &= String.Format("({0} {1} {2})", searchFields(i), queryOperator, searchValue) If i < searchFields.Length - 1 Then queryString &= " OR " End If Next i End Select Return queryString End Function #End Region End Class End Namespace