Common Custom EditorTask
Common_CustomEditorTask_VBNet\CustomEditorTaskWebApp_VBNet\StandardEditorTaskPage.aspx.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
Public Partial Class StandardEditorTaskPage
  Inherits System.Web.UI.Page

  #Region "ASP.NET Page Life Cycle Event Handlers"
    ' Add event handlers for out-of-the-box EditorTask during Page load
    Protected Sub Page_Load(ByVal sender As Object, ByVal eventArgs As System.EventArgs) Handles Me.Load
        If Not Page.IsPostBack Then
            AddHandler EditorTask1.EditorPanelsCreated, AddressOf EditorTask1_EditorPanelsCreated
            AddHandler EditorTask1.ToolsCreated, AddressOf EditorTask1_ToolsCreated

            AddHandler EditorTask1.PreAttributeEdit, AddressOf EditorTask1_PreAttributeEdit
            AddHandler EditorTask1.PostAttributeEdit, AddressOf EditorTask1_PostAttributeEdit

            AddHandler EditorTask1.PreCommandExecute, AddressOf EditorTask1_PreCommandExecute
        End If
    End Sub
    Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRender
        ' Determine whether the MapResourceManager has non-pooled resources and store in session
        If Not Page.IsPostBack Then
            Session("HasNonPooledResources") = HasNonPooledResources()
        End If
    End Sub

#End Region

  #Region "Web ADF EditorTask Event Handlers"

  Private Sub EditorTask1_PreCommandExecute(ByVal sender As Object, ByVal preCommandExecuteEventArgs As ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.PreCommandExecuteEventArgs)
    ' Cancel the DeleteFeature command if the active edit layer is AddressPoints
    Dim commandName As String = preCommandExecuteEventArgs.ServerAction.ToolbarItemInfo.Name
    Dim datasetName As String = preCommandExecuteEventArgs.ServerAction.DataSet.Name
        If commandName.Equals("DeleteFeature") AndAlso datasetName.Equals("Montgomery.DBO.Parcels") Then
            preCommandExecuteEventArgs.Cancel = True
            preCommandExecuteEventArgs.ReturnMessage = "Cannot delete features in " & datasetName
        End If
  End Sub

  Private Sub EditorTask1_PreAttributeEdit(ByVal sender As Object, ByVal preAttributeEditEventArgs As ESRI.ArcGIS.ADF.ArcGISServer.Editor.PreAttributeEditEventArgs)
    ' If the an attribute is edited, check the fields of the feature being edited
    ' for a field named "UPDATEDBY".  If present, and the current user is authenticated,
    ' set the value of the field to the user name.
    Dim fieldIndex As Integer = preAttributeEditEventArgs.Feature.Table.FindField("UPDATEDBY")

    If fieldIndex > -1 Then
      Dim authenticatedUserName As String = Context.User.Identity.Name
      If (Not String.IsNullOrEmpty(authenticatedUserName)) Then
                preAttributeEditEventArgs.Feature.Value(fieldIndex) = authenticatedUserName
      End If
    End If
  End Sub

  Private Sub EditorTask1_PostAttributeEdit(ByVal sender As Object, ByVal postAttributeEditEventArgs As ESRI.ArcGIS.ADF.ArcGISServer.Editor.PostAttributeEditEventArgs)
    ' If an attribute edit is unsuccessful, return exception message in a browser alert dialog.
    If (Not postAttributeEditEventArgs.Successful) Then
      postAttributeEditEventArgs.ReturnMessage = postAttributeEditEventArgs.Exception.Message
    End If
  End Sub

  Private Sub EditorTask1_EditorPanelsCreated(ByVal sender As Object, ByVal editorPanelsCreatedEventArgs As ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditorPanelsCreatedEventArgs)
    ' Create instance of new Editor Panel that contains a CreateFeature tool
    Dim newCreateFeaturePanel As CustomCreateFeaturePanel = New CustomCreateFeaturePanel(EditorTask1)

    ' Insert at the beginning (top) of the panels collection in the Editor
    editorPanelsCreatedEventArgs.EditorPanels.Insert(0, newCreateFeaturePanel)


    ' If using the out-of-the-box EditorTask and CreateFeature tool,
    ' the exiting CreateFeaturePanel cannot be removed.   The CreateFeature tool
    ' uses the FeatureLabel property on the CreateFeaturePanel returned from Editor.NewFeatureCreator.
    'e.EditorPanels.Remove(editorPanel);
    Dim editorPanel As ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditorPanel = newCreateFeaturePanel.ParentEditor.NewFeatureCreator
    editorPanel.Visible = False
  End Sub

  Private Sub EditorTask1_ToolsCreated(ByVal sender As Object, ByVal toolsCreatedEventArgs As ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.ToolsCreatedEventArgs)
    If toolsCreatedEventArgs.Parent Is EditorTask1.Editor.ExistingFeatureEditor Then
      ' The out-of-the-box EditExistingFeaturePanel contains two toolbars: GeometryToolbar1 and GeometryToolbar2
      For Each editorToolbar As ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.EditorToolbar In toolsCreatedEventArgs.Toolbars
        If editorToolbar.ID = "GeometryToolbar1" Then
          ' Add custom Clip tool to the GeometryToolbar1 toolbar in the EditExistingFeaturePanel
          Dim clipEditorTool As ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.EditorTool = New ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.EditorTool("Clip", (CType(toolsCreatedEventArgs.Parent, ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditExistingFeaturePanel)).ParentEditor.MapID, False, ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.ToolGeometry.Line Or ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.ToolGeometry.Polygon, 1)
          clipEditorTool.ClientAction = ESRI.ArcGIS.ADF.Web.UI.WebControls.Constants.HTML_DRAG_RECTANGLE
          clipEditorTool.DefaultImage = "~/images/clip.png"
          clipEditorTool.SelectedImage = "~/images/clip_ON.png"
          clipEditorTool.HoverImage = "~/images/clip_OVER.png"
          clipEditorTool.ToolTip = "Clip feature(s)"
          clipEditorTool.ServerActionAssembly = "App_Code"
          clipEditorTool.ServerActionClass = "CustomEditorTools.ClipFeatures"

          editorToolbar.ToolbarItems.Add(clipEditorTool)

          ' Resize the toolbar to accommodate the new tool.
          editorToolbar.Width = New System.Web.UI.WebControls.Unit(editorToolbar.Width.Value + 35, System.Web.UI.WebControls.UnitType.Pixel)
        End If
      Next editorToolbar

      ' Add a new EditorToolbar to the EditExistingFeaturesPanel.  The EditorToolbar will 
      ' automatically set the toolbar group to other EditorToolbars in the Editor.
      Dim newEditorToolbar As ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.EditorToolbar = New ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.EditorToolbar()
      newEditorToolbar.ToolbarStyle = ESRI.ArcGIS.ADF.Web.UI.WebControls.ToolbarStyle.ImageOnly
      newEditorToolbar.ID = "MyCustomToolbar"
      newEditorToolbar.BuddyControlType = ESRI.ArcGIS.ADF.Web.UI.WebControls.BuddyControlType.Map
      newEditorToolbar.BuddyControls.Add(New ESRI.ArcGIS.ADF.Web.UI.WebControls.BuddyControl((CType(toolsCreatedEventArgs.Parent, ESRI.ArcGIS.ADF.ArcGISServer.Editor.EditExistingFeaturePanel)).ParentEditor.MapID))

      Dim verticeCountEditorCommand As ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.EditorCommand = New ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.EditorCommand("VerticeCount", ESRI.ArcGIS.ADF.ArcGISServer.Editor.Tools.ToolGeometry.All, 1)
      verticeCountEditorCommand.DefaultImage = "~/images/verticecount.png"
      verticeCountEditorCommand.SelectedImage = "~/images/verticecount_ON.png"
      verticeCountEditorCommand.HoverImage = "~/images/verticecount_OVER.png"
      verticeCountEditorCommand.ToolTip = "Count the number of vertices in the selected feature"
      verticeCountEditorCommand.ServerActionAssembly = "App_Code"
      verticeCountEditorCommand.ServerActionClass = "CustomEditorTools.VerticeCount"

      newEditorToolbar.ToolbarItems.Add(verticeCountEditorCommand)
      ' If Width is 0, JavaScript error Toolbars[..] is null
      newEditorToolbar.Width = New System.Web.UI.WebControls.Unit(newEditorToolbar.ToolbarItems.Count * 35, System.Web.UI.WebControls.UnitType.Pixel)

      toolsCreatedEventArgs.Toolbars.Add(newEditorToolbar)
    End If
  End Sub

  #End Region

  #Region "Instance Methods"

  Private Sub FilterAttributes()
    ' Get the ArcGIS Server Local MapFunctionality associated with the EditorTask
    Dim agsLocalMapFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality = EditorTask1.Editor.MapFunctionality

    Dim layerIDs As String() = Nothing
    Dim layerNames As String() = Nothing
    agsLocalMapFunctionality.GetLayers(layerIDs, layerNames)

    ' Iterate through feature layers in the MapFunction (map resource) and set
    ' attribute display parameters when editing attributes in the EditAttributesPanel.
    Dim i As Integer = 0
    Do While i < layerIDs.Length
      Dim layerName As String = layerNames(i)
      Dim layerID As Integer = System.Int32.Parse(layerIDs(i))
            If layerName = "Parcels" Then
                Dim attributeDisplayInfo As ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayInfo = New ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayInfo(layerID, ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayMode.ReadOnly)
                attributeDisplayInfo.Overrides.Add(New ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayOverride("Parcel_Id", ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayMode.Editable))
                EditorTask1.AttributeDisplay.AttributeDisplayInfos.Add(attributeDisplayInfo)
            ElseIf layerName = "Road centerline" Then
                Dim attributeDisplayInfo As ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayInfo = New ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayInfo(layerID, ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayMode.Editable)
                attributeDisplayInfo.Overrides.Add(New ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayOverride("Name", ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayMode.ReadOnly))
                EditorTask1.AttributeDisplay.AttributeDisplayInfos.Add(attributeDisplayInfo)
            ElseIf layerName = "Blocks" Then
                Dim attributeDisplayInfo As ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayInfo = New ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayInfo(layerID, ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayMode.Hidden)
                attributeDisplayInfo.Overrides.Add(New ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayOverride("Res", ESRI.ArcGIS.ADF.ArcGISServer.Editor.AttributeDisplayMode.Editable))
                EditorTask1.AttributeDisplay.AttributeDisplayInfos.Add(attributeDisplayInfo)
            End If
      i += 1
    Loop
  End Sub

  Private Sub ReleaseContext()
    ' Loop through session variables and release any that are server contexts
    Dim serverContext As ESRI.ArcGIS.Server.IServerContext
    Dim i As Integer = 0
    Do While i < Session.Count
      ' Attempt to get a reference to the current session variable as a server context
      serverContext = TryCast(Session(i), ESRI.ArcGIS.Server.IServerContext)
      If Not serverContext Is Nothing Then
        ' If the current session variable is a server context, release it.
        serverContext.RemoveAll()
        serverContext.ReleaseContext()
      End If
      i += 1
    Loop

    ' Clear session variables.  This will force creation of a new session if the user returns
    ' to the page.  Otherwise, session variables may still be present and will cause errors.
    Session.RemoveAll()

    ' Loop through the map resources referred to by MapResourceManager1 and explicitly dispose
    ' any that are ArcGIS local map resources
    Dim mapResourceLocal As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal
    For Each mapResourceItem As ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceItem In MapResourceManager1.ResourceItems
      mapResourceLocal = TryCast(mapResourceItem.Resource, ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal)
      If Not mapResourceLocal Is Nothing Then
        mapResourceLocal.Dispose()
      End If
    Next mapResourceItem
  End Sub

  Private Function HasNonPooledResources() As Boolean
    ' Define a boolean and set it to false by default, indicating no non-pooled resources
    Dim hasNonPooledResource As Boolean = False

    ' Now go through all resources and find any non-pooled local resources
    Dim mapResourceLocal As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal = Nothing
    Dim gisDataSourceLocal As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.GISDataSourceLocal = Nothing

    ' First, check the map resourceItems
    For Each mapResourceItem As ESRI.ArcGIS.ADF.Web.UI.WebControls.MapResourceItem In MapResourceManager1.ResourceItems
      If Not mapResourceItem Is Nothing Then
        ' Get the local ArcGIS Server map resource underlying the current resource item
        mapResourceLocal = TryCast(mapResourceItem.Resource, ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal)

        If Not mapResourceLocal Is Nothing Then
          If (Not MapResourceManager1.IsInitialized(mapResourceItem)) Then
            MapResourceManager1.Initialize(mapResourceItem)
          End If

          ' Get the local ArcGIS Server GIS data source from the local map resource
          gisDataSourceLocal = TryCast(mapResourceLocal.DataSource, ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.GISDataSourceLocal)

          ' If the server object is not pooled, set the has non-pooled resource boolean to true
          If (Not gisDataSourceLocal.Connection.IsServerObjectPooled(mapResourceLocal.ServerContextInfo.ServerObjectName, "MapServer")) Then
            hasNonPooledResource = True
          End If

        End If
      End If
    Next mapResourceItem
    Return hasNonPooledResource
  End Function

  #End Region

    Protected Sub PostbackManager1_RequestReceived(ByVal sender As Object, ByVal args As PostbackManager_VBNet.AdfRequestEventArgs) Handles PostbackManager1.RequestReceived
        ' Parse the request arguments
        Dim requestArgs As System.Collections.Specialized.NameValueCollection = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection(args.RequestArguments)

        ' Check the event argument and draw or clear graphics accordingly
        Select Case requestArgs("EventArg")
            Case "Dispose"
                If CBool(Session("HasNonPooledResources")) Then
                    ReleaseContext()
                End If
        End Select
    End Sub
End Class