ArcGIS Add Dynamic Data
ArcGIS_AddDynamicData_VBNet\MoveLayer_ADF.aspx.vb
' Copyright 2009 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.
' 

' Illustrates how the move an existing layer in a pooled ArcGIS Server map service

Imports Microsoft.VisualBasic
Imports System
Public Partial Class MoveLayer_ADF
  Inherits System.Web.UI.Page
  Implements System.Web.UI.ICallbackEventHandler
  #Region "Instance Variable Declarations"

  Public m_adfCallbackFunctionString As String
  Private m_callbackResultCollection As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResultCollection = New ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResultCollection()
  Private m_serverObjectStateModifier As ServerObjectStateModifier = Nothing

  ' Specify the name of the resource containing the layer to move
  Private m_targetResourceName As String = "MapResourceItem0"
  ' Specify the name of the layer to move
  Private m_targetLayerName As String = "Highways"

  #End Region

  #Region "ASP.NET Page Life Cycle Event Handlers"

  Protected Sub Page_PreInit(ByVal sender As Object, ByVal e As System.EventArgs)
    ' Instantiate a class-level ServerObjectStateModifier to use in moving the layer
    m_serverObjectStateModifier = New ServerObjectStateModifier()
  End Sub

  Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
    Try
      ' Define the parameters for a browser call to the WebForm_DoCallback JavaScript function
      ' via the GetCallbackEventReference function.  The GetCallbackEventReference function returns 
      ' the syntax for initiating a callback (i.e a call to WebForm_DoCallback) with the passed-in 
      ' parameters.  Here the parameters are defined as follows:
      ' this - the Page will handle the callback request
      ' "message" - a JavaScript variable named "message" will contain argument-value pairs passed 
      '      to the callback server-side
      ' "processCallbackResult" - name of the JavaScript function to process the callback 
      '      results from the server.  This function is the callback results handler included with 
      '      the Web ADF JavaScript Library.
      ' "context" - a JavaScript variable named "context" which can be used by the client to
      '      indicate the origin of the callback
      ' "postBackError" - name of the JavaScript function that will process errors returned during 
      '      callback processing.  This is the callback error handler included with the Web ADF 
      '      JavaScript Library
      ' true - define whether the callback is synchronous or asynchronous.  True is asynchronous.        
      m_adfCallbackFunctionString = Page.ClientScript.GetCallbackEventReference(Me, "message", "processCallbackResult", "context", "postBackError", True)

      ' If the target layer has been moved (indicated by the session variable storing the moved layer's current index
      ' being populated), then we need to move it again to the last index at which it was located so that the Web ADF 
      ' components accessing the map resource are aware of the correct layer position.  
      If Not Session("currentLayerIndex") Is Nothing Then
        ' Get the layer's target resource and call the method to move the target layer to its current index, as stored
        ' in session
        Dim agsMapFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality = CType(Map1.GetFunctionality(m_targetResourceName), ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality)
        Dim mapResourceLocal As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal = CType(agsMapFunctionality.Resource, ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal)

        m_serverObjectStateModifier.MoveLayer(mapResourceLocal, m_targetLayerName, CInt(Fix(Session("currentLayerIndex"))))
      End If

      AddHandler MapResourceManager1.ResourcesDispose, AddressOf MapResourceManager1_ResourcesDispose
    Catch exception As System.Exception
      ' Check whether the page is loading as a result of a callback.  If not, assume that a full page postback
      ' is occuring, since this page implements the callback framework (and not partial postback).
      If Page.IsCallback Then
        ' Get a callback result that will show an alert with information pertaining to the exception
        Dim errorCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = Utility.GetErrorCallback(exception)
        ' Get the control that initiated the postback
        Dim control As System.Web.UI.Control = Utility.GetPostBackControl(Page)

        ' If the control is a Web ADF Control (i.e. WebCotnrol or CompositeControl), add the error 
        ' callback to that control's callback results.  Otherwise, add the error callback to the 
        ' callback results collection member variable, which will be passed to the client in 
        ' GetCallbackResult.
        If TypeOf control Is ESRI.ArcGIS.ADF.Web.UI.WebControls.WebControl Then
          Dim adfWebControl As ESRI.ArcGIS.ADF.Web.UI.WebControls.WebControl = TryCast(control, ESRI.ArcGIS.ADF.Web.UI.WebControls.WebControl)
          adfWebControl.CallbackResults.Add(errorCallbackResult)
        ElseIf TypeOf control Is ESRI.ArcGIS.ADF.Web.UI.WebControls.CompositeControl Then
          Dim adfCompositeControl As ESRI.ArcGIS.ADF.Web.UI.WebControls.CompositeControl = TryCast(control, ESRI.ArcGIS.ADF.Web.UI.WebControls.CompositeControl)
          adfCompositeControl.CallbackResults.Add(errorCallbackResult)
        Else
          m_callbackResultCollection.Add(errorCallbackResult)
        End If
      Else
        ' Since the page is in full postback, write the javascript alert code directly to the response
        Dim jsErrorAlert As String = String.Format("<script>{0}</script>", Utility.GetJavaScriptErrorString(exception))
        Response.Write(jsErrorAlert)
      End If
    End Try
  End Sub

  #End Region

  #Region "Web ADF Control Event Handlers"

  Private Sub MapResourceManager1_ResourcesDispose(ByVal sender As Object, ByVal e As System.EventArgs)
    ' If the target layer has been moved (indicated by the session variable storing the layer's initial position), then we 
    ' need to move it back to its original position in the map resource before the server context created as a result of 
    ' the current page request is released.  Otherwise, the target layer will be in the altered position outside the scope
    ' of this page request, so clients accessing the map service will see the layer in the new position
    If Not Session("originalLayerIndex") Is Nothing Then
      ' Get the layer's target resource and call the method to move the layer back to its original position
      Dim agsMapFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality = CType(Map1.GetFunctionality(m_targetResourceName), ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality)
      Dim mapResourceLocal As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal = CType(agsMapFunctionality.Resource, ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal)

      m_serverObjectStateModifier.MoveLayer(mapResourceLocal, m_targetLayerName, CInt(Fix(Session("originalLayerIndex"))))
    End If
  End Sub

  #End Region

  #Region "ICallbackEventHandler Members"

  ' Receives the arguments packaged in the callback on the client.  We parse those arguments here and 
  ' initiate server-side logic accordingly.
  Public Sub RaiseCallbackEvent(ByVal eventArgs As String) Implements System.Web.UI.ICallbackEventHandler.RaiseCallbackEvent
    Try
      ' Get the resource containing the layer to be moved
      Dim agsMapFunctionality As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality = CType(Map1.GetFunctionality(m_targetResourceName), ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapFunctionality)
      Dim mapResourceLocal As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal = CType(agsMapFunctionality.Resource, ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal)

      ' Parse the callback string passed from the client to the server into separate
      ' arguments using the Web ADF's callback parsing utility.
      Dim callbackArgsCollection As System.Collections.Specialized.NameValueCollection = ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackUtility.ParseStringIntoNameValueCollection(eventArgs)

      ' Get the current index of the layer.  If the session variable storing the layer's original index has not
      ' been populated, populate it with the current index.  This will be used to restore the layer to its
      ' original position in the map service.
      Dim currentLayerIndex As Integer
      If Session("originalLayerIndex") Is Nothing Then
        currentLayerIndex = GetLayerIndex(mapResourceLocal, m_targetLayerName)
        Session("originalLayerIndex") = currentLayerIndex
        Session("currentLayerIndex") = currentLayerIndex
      Else
        currentLayerIndex = CInt(Fix(Session("currentLayerIndex")))
      End If

      ' Check the callback event argument
      Select Case callbackArgsCollection("EventArg")
        Case "moveLayerUp"
          ' Call the method to move the layer, passing in a layer index one less than the current one, which will move the
          ' layer up one position.
          currentLayerIndex = m_serverObjectStateModifier.MoveLayer(mapResourceLocal, m_targetLayerName, currentLayerIndex - 1)
          If currentLayerIndex <> -1 Then
            ' If a non-negative layer index was returned then the layer was moved successfully.  Update the current layer
            ' index session variable and refresh the Map and Toc so they reflect the layer's new position.
            Session("currentLayerIndex") = currentLayerIndex
            RefreshMapAndToc()
          End If
        Case "moveLayerDown"
          ' Call the method to move the layer, passing in a layer index one more than the current one, which will move the
          ' layer up one position.
          currentLayerIndex = m_serverObjectStateModifier.MoveLayer(mapResourceLocal, m_targetLayerName, currentLayerIndex + 1)
          If currentLayerIndex <> -1 Then
            ' If a non-negative layer index was returned then the layer was moved successfully.  Update the current layer
            ' index session variable and refresh the Map and Toc so they reflect the layer's new position.
            Session("currentLayerIndex") = currentLayerIndex
            RefreshMapAndToc()
          End If
      End Select
    Catch exception As System.Exception
      ' Get a callback result that will alert the user of the error and add it to the callback results collection
      Dim errorCallbackResult As ESRI.ArcGIS.ADF.Web.UI.WebControls.CallbackResult = Utility.GetErrorCallback(exception)
      m_callbackResultCollection.Add(errorCallbackResult)
    End Try
  End Sub

  ' The last server-side method called before the callback returns to the browser, GetCallbackResult
  ' is where the server-side result of the callback is passed back to the browser as a string for
  ' processing by the client.
  Public Function GetCallbackResult() As String Implements System.Web.UI.ICallbackEventHandler.GetCallbackResult
    Return m_callbackResultCollection.ToString()
  End Function

  #End Region

  #Region "Instance Properties"

  ' Property allowing client-side access to the client callback function string.  This string
  ' contains the necessary JavaScript syntax to initiate a callback with the parameters specified
  ' in GetCallbackEventReference (in Page_Load).
  Public Property AdfCallbackFunctionString() As String
    Get
      Return m_adfCallbackFunctionString
    End Get
    Set
      m_adfCallbackFunctionString = Value
    End Set
  End Property

  #End Region

  #Region "Instance Methods"

  ' Retrieves the index of the layer indicated by the passed-in name from the passed-in resource
  Private Function GetLayerIndex(ByVal mapResourceLocal As ESRI.ArcGIS.ADF.Web.DataSources.ArcGISServer.MapResourceLocal, ByVal layerName As String) As Integer
    ' Get the map underlying the passed-in map resource
    Dim mapServerObjects As ESRI.ArcGIS.Carto.IMapServerObjects = CType(mapResourceLocal.MapServer, ESRI.ArcGIS.Carto.IMapServerObjects)
        Dim aoMap As ESRI.ArcGIS.Carto.IMap = mapServerObjects.Map(mapResourceLocal.DataFrame)

        ' Get a reference to the layer with the passed-in name from the map
        Dim enumLayer As ESRI.ArcGIS.Carto.IEnumLayer = aoMap.Layers(Nothing, True)
        Dim currentLayer As ESRI.ArcGIS.Carto.ILayer = enumLayer.Next()
    Dim layerIndex As Integer = 0

        Do While currentLayer IsNot Nothing
            If currentLayer.Name = layerName Then
                Exit Do
            End If
            currentLayer = enumLayer.Next()
            layerIndex += 1
        Loop

    Return layerIndex
  End Function

  ' Refreshes the Map and Toc controls and populates the callback results member variable with the
  ' resulting callback results 
  Private Sub RefreshMapAndToc()
    Toc1.Refresh()
    Map1.CallbackResults.CopyFrom(Toc1.CallbackResults)

    Map1.RefreshResource(m_targetResourceName)
    m_callbackResultCollection.CopyFrom(Map1.CallbackResults)
  End Sub

  #End Region
End Class