Common Web Mapping Application
Common_WebMappingApp_VBNet\Measure.ascx.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 System
Imports System.Data
Imports System.Configuration
Imports System.Collections
Imports System.Collections.Specialized
Imports System.Web
Imports System.Web.Security
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.Web.UI.WebControls.WebParts
Imports System.Web.UI.HtmlControls
Imports ESRI.ArcGIS.ADF.Web
Imports ESRI.ArcGIS.ADF.Web.UI.WebControls
Imports ESRI.ArcGIS.ADF.Web.DataSources
Imports ESRI.ArcGIS.ADF.Web.Geometry

Namespace WebMapApp

    Public Enum MapUnit
        Resource_Default
        Degrees
        Feet
        Meters
    End Enum 'MapUnit

    Public Enum MeasureUnit
        Feet
        Kilometers
        Meters
        Miles
    End Enum 'MeasureUnit

    Public Enum AreaUnit
        Acres
        Sq_Feet
        Sq_Kilometers
        Sq_Meters
        Sq_Miles
        Hectares
    End Enum 'AreaUnit


    Partial Class Measure
        Inherits System.Web.UI.UserControl
        Implements IPostBackEventHandler
        Implements ICallbackEventHandler

        Private _resourceManger As MapResourceManager
        Private _mapFunctionality As IMapFunctionality
        Public CallbackInvocation As String = ""
        Private _mapBuddyId As String = "Map1"
        Private _id As String
        Private _map As Map
        Private _mapUnits As MapUnit = MapUnit.Degrees
        Private _startMapUnits As MapUnit = MapUnit.Degrees
        Private _fallbackMapUnits As MapUnit = MapUnit.Degrees
        Private _measureUnits As MeasureUnit = MeasureUnit.Miles
        Private _areaUnits As AreaUnit = AreaUnit.Sq_Miles
        Private _numberDecimals As Double = 4
        Private callbackArg As String


        Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
            _id = Me.ClientID
            Dim page As Page = Me.Page
            ' find the map control
            If (_mapBuddyId Is Nothing Or _mapBuddyId.Length = 0) Then
                _mapBuddyId = "Map1"
            End If
            _map = page.FindControl(_mapBuddyId)
            ' find the map resource manager
            _resourceManger = page.FindControl(_map.MapResourceManager)
            CallbackInvocation = CallbackFunctionString
        End Sub

        Protected ReadOnly Property CallbackFunctionString() As String
            Get
                If ScriptManager.GetCurrent(Page) Is Nothing Then
                    Return Page.ClientScript.GetCallbackEventReference(Me, "argument", "ESRI.ADF.System.processCallbackResult", "context", "postBackError", False)
                Else
                    Return String.Format("__esriDoPostBack('{0}','{1}', argument, ESRI.ADF.System.ProcessMSAjaxCallbackResult, context)", Me.UniqueID, Me.ClientID)
                End If
            End Get
        End Property

        Protected Sub Page_PreRender(ByVal sender As Object, ByVal e As EventArgs)
            MeasureDisplayPanel.InnerHtml = WriteInitialContents()
            If Not ScriptManager.GetCurrent(Page) Is Nothing Then
                ScriptManager.GetCurrent(Me.Page).RegisterAsyncPostBackControl(Me)
            End If
        End Sub

        Private ReadOnly Property MapFunctionality() As IMapFunctionality
            Get
                If _mapFunctionality Is Nothing Then
                    ' use the primary resouce, if defined
                    Dim primeResource As String = _map.PrimaryMapResource
                    Dim resource As IGISResource = Nothing
                    If primeResource <> Nothing And primeResource.Length > 0 Then
                        resource = _resourceManger.GetResource(primeResource)
                    End If
                    If resource Is Nothing Then
                        Dim i As Integer
                        For i = 0 To _resourceManger.ResourceItems.Count - 1 Step i + 1
                            resource = _resourceManger.GetResource(i)
                            If Not resource Is Nothing Then
                                Exit For
                            End If
                        Next
                    End If
                    If Not resource Is Nothing Then
                        _mapFunctionality = CType(resource.CreateFunctionality(GetType(IMapFunctionality), "mapFunctionality"), IMapFunctionality)
                    End If
                End If
                Return _mapFunctionality
            End Get
        End Property


        Private Function ProcessMeasureRequest(ByVal queryString As NameValueCollection) As String

            Dim o As Object = Session("MeasureMapUnits")
            If Not (o Is Nothing) Then
                _mapUnits = CType([Enum].Parse(GetType(MapUnit), o.ToString()), MapUnit)
            ElseIf _startMapUnits = MapUnit.Resource_Default Then
                _mapUnits = GetResourceDefaultMapUnit()
            Else
                _mapUnits = _startMapUnits
            End If
            Dim eventArg As String = queryString("EventArg")
            Dim vectorAction As String = queryString("VectorMode")
            Dim coordPairs(), xys() As String
            Dim coordString As String = queryString("coords")
            If coordString Is Nothing And coordString.Length = 0 Then
                coordString = ""
            End If

            coordPairs = coordString.Split(Char.Parse("|"))
            Dim mapUnitString As String = queryString("MapUnits")
            Dim forceRefresh As Boolean = (queryString("refresh") = "true")
            If mapUnitString Is Nothing Then mapUnitString = ""
            If mapUnitString.Length > 0 Then
                _mapUnits = CType([Enum].Parse(GetType(MapUnit), mapUnitString), MapUnit)
            End If
            Session("MeasureMapUnits") = _mapUnits
            Dim measureUnitString As String = queryString("MeasureUnits")
            If measureUnitString Is Nothing Then measureUnitString = ""
            If measureUnitString.Length > 0 Then _measureUnits = CType([Enum].Parse(GetType(MeasureUnit), measureUnitString), MeasureUnit)
            Dim areaUnitstring As String = queryString("AreaUnits")
            If areaUnitstring Is Nothing Then areaUnitstring = ""
            If areaUnitstring.Length > 0 Then _areaUnits = CType([Enum].Parse(GetType(AreaUnit), areaUnitstring), AreaUnit)
            Dim response As String = Nothing
            Dim points As New PointCollection()
            Dim dPoints As New PointCollection()
            Dim distances As New ArrayList()
            Dim totalDistance As Double = 0
            Dim segmentDistance As Double = 0
            Dim area As Double = 0
            Dim perimeter As Double = 0
            Dim roundFactor As Double = Math.Pow(10, _numberDecimals)
            Dim xD, yD, tempDist, tempDist2, tempArea, x1, x2, y1, y2 As Double
            Dim transformationParameters As TransformationParams = _map.GetTransformationParams(TransformationDirection.ToMap)
            If (vectorAction = "measure") Then

                If Not coordPairs Is Nothing And coordPairs.Length > 1 Then
                    For cp As Integer = 0 To coordPairs.Length - 1
                        xys = coordPairs(cp).Split(Char.Parse(":"))
                        points.Add(New Point(Convert.ToDouble(xys(0), System.Globalization.CultureInfo.InvariantCulture), Convert.ToDouble(xys(1), System.Globalization.CultureInfo.InvariantCulture)))
                        If cp > 0 Then
                            ' check for duplicate points from double click.... Firefox will send coords for both clicks, causing segmentDistance to be zero.
                            If (Not points(cp - 1).X = points(cp).X OrElse Not points(cp - 1).Y = points(cp).Y) Then
                                If _mapUnits = MapUnit.Degrees Then
                                    ' use great circle formula
                                    tempDist = DegreeToFeetDistance(points(cp - 1).X, points(cp - 1).Y, points(cp).X, points(cp).Y)
                                    y1 = DegreeToFeetDistance(points(cp).X, points(cp).Y, points(cp).X, 0)
                                    x1 = DegreeToFeetDistance(points(cp).X, points(cp).Y, 0, points(cp).Y)
                                    dPoints.Add(New Point(x1, y1))
                                    segmentDistance = ConvertUnits(tempDist, MapUnit.Feet, _measureUnits)
                                Else
                                    ' get third side of triangle for distance
                                    xD = Math.Abs(points(cp).X - points(cp - 1).X)
                                    yD = Math.Abs(points(cp).Y - points(cp - 1).Y)
                                    tempDist = Math.Sqrt(Math.Pow(xD, 2) + Math.Pow(yD, 2))
                                    segmentDistance = ConvertUnits(tempDist, _mapUnits, _measureUnits)
                                End If
                                distances.Add(segmentDistance)
                                totalDistance += segmentDistance
                                segmentDistance = Math.Round(segmentDistance * roundFactor) / roundFactor
                                totalDistance = Math.Round(totalDistance * roundFactor) / roundFactor
                            End If
                        Else
                            If (_mapUnits = MapUnit.Degrees) Then
                                y1 = DegreeToFeetDistance(points(cp).X, points(cp).Y, points(cp).X, 0)
                                x1 = DegreeToFeetDistance(points(cp).X, points(cp).Y, 0, points(cp).Y)
                                dPoints.Add(New Point(x1, y1))
                            End If
                        End If
                    Next
                End If
                If (eventArg = "polygon") Then
                    If (points.Count > 2 OrElse forceRefresh) Then
                        If (_mapUnits = MapUnit.Degrees) Then
                            tempDist = DegreeToFeetDistance(points(points.Count - 1).X, points(points.Count - 1).Y, points(0).X, points(0).Y)
                            tempDist2 = ConvertUnits(tempDist, MapUnit.Feet, _measureUnits)
                            distances.Add(tempDist2)
                            dPoints.Add(dPoints(0))
                        Else
                            xD = Math.Abs(points(points.Count - 1).X - points(0).X)
                            yD = Math.Abs(points(points.Count - 1).Y - points(0).Y)
                            tempDist = Math.Sqrt(Math.Pow(xD, 2) + Math.Pow(yD, 2))
                            tempDist2 = ConvertUnits(tempDist, _mapUnits, _measureUnits)
                            distances.Add(tempDist2)
                        End If
                        points.Add(points(0))
                        perimeter = totalDistance + tempDist2
                        ' add area calculation
                        tempArea = 0
                        Dim mUnits As MapUnit = _mapUnits
                        Dim xDiff As Double = 0
                        Dim yDiff As Double = 0
                        If (_mapUnits = MapUnit.Degrees) Then
                            points = dPoints
                            mUnits = MapUnit.Feet
                        End If
                        For j As Integer = 0 To points.Count - 2
                            x1 = Convert.ToDouble(points(j).X, System.Globalization.CultureInfo.InvariantCulture)
                            x2 = Convert.ToDouble(points(j + 1).X, System.Globalization.CultureInfo.InvariantCulture)
                            y1 = Convert.ToDouble(points(j).Y, System.Globalization.CultureInfo.InvariantCulture)
                            y2 = Convert.ToDouble(points(j + 1).Y, System.Globalization.CultureInfo.InvariantCulture)
                            xDiff = x2 - x1
                            yDiff = y2 - y1
                            tempArea += x1 * yDiff - y1 * xDiff
                        Next
                        tempArea = Math.Abs(tempArea) / 2
                        area = ConvertAreaUnits(tempArea, mUnits, _areaUnits)
                        perimeter = Math.Round(perimeter * roundFactor) / roundFactor
                        area = Math.Round(area * roundFactor) / roundFactor
                    Else
                        response = String.Format("<table cellspacing='0' ><tr><td>Perimeter: </td><td align='right' id='tdperimiter'> 0</td><td >{0}</td></tr><tr><td>Area:</td><td align='right' id='tdarea'>0 </td><td>{1}</td></tr></table>", WriteMeasureUnitDropDown(), WriteAreaUnitDropDown())
                    End If

                ElseIf (eventArg = "polyline") Then
                    If points.Count < 3 OrElse forceRefresh Then
                        response = String.Format("<table cellspacing='0' ><tr><td>Segment: </td><td align='right' id='tdsegment'>{0} </td><td>{1}</td></tr><tr><td>Total Length:</td><td align='right' id='tdtotaldistance'>{2} </td><td>{3}</td></tr></table>", segmentDistance, _measureUnits, totalDistance, WriteMeasureUnitDropDown())
                    End If
                ElseIf (eventArg = "point" And coordPairs.Length > 0) Then
                    xys = coordPairs(0).Split(Char.Parse(":"))
                    response = String.Format("<table cellspacing='0' ><tr><td>X Coordinate:</td><td align='right' dir='ltr'>{0}</td></tr><tr><td>Y Coordinate:</td><td align='right' dir='ltr'>{1}</td></tr></table>", (Math.Round(Convert.ToDouble(xys(0), System.Globalization.CultureInfo.InvariantCulture) * roundFactor) / roundFactor), (Math.Round(Convert.ToDouble(xys(1), System.Globalization.CultureInfo.InvariantCulture) * roundFactor) / roundFactor))


                End If
            End If
            Dim coll As CallbackResultCollection = New CallbackResultCollection()
            coll.Add(New CallbackResult("", "", "invoke", "measureComplete", _
             New Object() {response, _id, String.Format("{0}", area), String.Format("{0}", perimeter), String.Format("{0}", segmentDistance), String.Format("{0}", totalDistance)}))
            Return coll.ToString()
        End Function

        Private Function CheckFormMeasureUnits(ByVal unit As String) As String
            Dim response As String = ""
            If unit = _measureUnits.ToString() Then
                response = "selected=""selected"""
            End If
            Return response
        End Function 'CheckFormMeasureUnits

        Private Function CheckFormAreaUnits(ByVal unit As String) As String
            Dim response As String = ""
            If unit = _areaUnits.ToString() Then
                response = "selected=""selected"""
            End If
            Return response
        End Function 'CheckFormAreaUnits

        Private Function WriteMeasureUnitDropDown() As String
            Dim sb As New System.Text.StringBuilder()
            sb.Append("<select id=""MeasureUnits2"" onchange=""changeMeasureUnits()"" style=""font: normal 7pt Verdana; width: 100px;"">")
            Dim mArray As Array = [Enum].GetValues(GetType(MeasureUnit))
            Dim mu As MeasureUnit
            For Each mu In mArray
                sb.AppendFormat("<option value=""{0}"" {1}>{0}</option>", mu, CheckFormMeasureUnits(mu.ToString()))
            Next mu
            sb.Append("</select>")

            Return sb.ToString()
        End Function 'WriteMeasureUnitDropdown

        Private Function WriteAreaUnitDropDown() As String
            Dim sb As New System.Text.StringBuilder()
            sb.Append("<select id=""AreaUnits2"" onchange=""changeAreaUnits()"" style=""font: normal 7pt Verdana; width: 100px;"">")
            Dim aArray As Array = [Enum].GetValues(GetType(AreaUnit))
            Dim au As AreaUnit
            For Each au In aArray
                sb.AppendFormat("<option value=""{0}"" {1}>{0}</option>", au, CheckFormAreaUnits(au.ToString()))
            Next au
            sb.Append("</select>")

            Return sb.ToString()
        End Function 'WriteAreaUnitDropDown

        Private Function ConvertUnits(ByVal distance As Double, ByVal fromUnits As MapUnit, ByVal toUnits As MeasureUnit) As Double
            Dim mDistance As Double = distance
            If fromUnits = MapUnit.Feet Then
                If toUnits = MeasureUnit.Miles Then
                    mDistance = distance / 5280
                Else
                    If toUnits = MeasureUnit.Meters Then
                        mDistance = distance * 0.304800609601
                    Else
                        If toUnits = MeasureUnit.Kilometers Then
                            mDistance = distance * 0.0003048
                        End If
                    End If
                End If
            Else
                If toUnits = MeasureUnit.Miles Then
                    mDistance = distance * 0.0006213700922
                Else
                    If toUnits = MeasureUnit.Feet Then
                        mDistance = distance * 3.280839895
                    Else
                        If toUnits = MeasureUnit.Kilometers Then
                            mDistance = distance / 1000
                        End If
                    End If
                End If
            End If
            Return mDistance
        End Function 'ConvertUnits

        Private Function ConvertAreaUnits(ByVal area As Double, ByVal baseUnits As MapUnit, ByVal toUnits As AreaUnit) As Double
            Dim mArea As Double = area
            If baseUnits = MapUnit.Feet Then
                If toUnits = AreaUnit.Acres Then
                    mArea = area * 0.000022956
                Else
                    If toUnits = AreaUnit.Sq_Meters Then
                        mArea = area * 0.09290304
                    Else
                        If toUnits = AreaUnit.Sq_Miles Then
                            mArea = area * 0.00000003587
                        Else
                            If toUnits = AreaUnit.Sq_Kilometers Then
                                mArea = area * 0.09290304 / 1000000
                            Else
                                If toUnits = AreaUnit.Hectares Then
                                    mArea = area * 0.09290304 * 0.0001
                                End If
                            End If
                        End If
                    End If
                End If
            Else
                If baseUnits = MapUnit.Meters Then
                    If toUnits = AreaUnit.Acres Then
                        mArea = area * 0.0002471054
                    Else
                        If toUnits = AreaUnit.Sq_Miles Then
                            mArea = area * 0.0000003861003
                        Else
                            If toUnits = AreaUnit.Sq_Kilometers Then
                                mArea = area * 0.000001
                            Else
                                If toUnits = AreaUnit.Sq_Feet Then
                                    mArea = area * 10.76391042
                                Else
                                    If toUnits = AreaUnit.Hectares Then
                                        mArea = area * 0.0001
                                    End If
                                End If
                            End If
                        End If
                    End If
                End If
            End If
            Return mArea
        End Function 'ConvertAreaUnits

        Private Function DegreeToFeetDistance(ByVal x1 As Double, ByVal y1 As Double, ByVal x2 As Double, ByVal y2 As Double) As Double
            ' use great circle formula
            Dim Lat1 As Double = DegToRad(y1)
            Dim Lat2 As Double = DegToRad(y2)
            Dim Lon1 As Double = DegToRad(x1)
            Dim Lon2 As Double = DegToRad(x2)
            Dim LonDist As Double = Lon1 - Lon2
            Dim LatDist As Double = Lat1 - Lat2
            Dim x As Double = Math.Pow(Math.Sin((LatDist / 2)), 2) + Math.Cos(Lat1) * Math.Cos(Lat2) * Math.Pow(Math.Sin((LonDist / 2)), 2)
            x = 2 * Math.Asin(Math.Min(1, Math.Sqrt(x)))
            x = (3963 - 13 * Math.Sin(((Lat1 + Lat2) / 2))) * x
            ' in miles... convert to feet and use that as base
            Return x * 5280
        End Function 'DegreeToFeetDistance

        Private Function DegToRad(ByVal degrees As Double) As Double
            Return Convert.ToDouble((degrees * Math.PI / 180))
        End Function 'DegToRad

        Private Function GetResourceDefaultMapUnit() As MapUnit
            Dim mUnit As MapUnit = MapUnit.Degrees
            Try
                Dim mu As Units = MapFunctionality.Units
                If mu = Units.DecimalDegrees Then
                    mUnit = MapUnit.Degrees
                Else
                    If mu = Units.Feet Then
                        mUnit = MapUnit.Feet
                    Else
                        If mu = Units.Meters Then
                            mUnit = MapUnit.Meters
                        End If
                    End If
                End If
            Catch
                ' cannot get units from resource... default to fallback value set in declaration
                mUnit = _fallbackMapUnits
            End Try
            Return mUnit
        End Function 'GetResourceDefaultMapUnit 

        Public Function CanGetUnits() As Boolean
            For Each mapFunc As ESRI.ArcGIS.ADF.Web.DataSources.IMapFunctionality In _map.GetFunctionalities
                Try
                    Dim units As Units = mapFunc.Units
                    Return True
                Catch ex As Exception
                    ' Getting units failed
                End Try
            Next
            Return False
        End Function

        Private Function WriteInitialContents() As String
            Dim sb As New System.Text.StringBuilder()
            ' set up tool buttons 
            sb.AppendFormat("<table cellpadding='0' cellspacing='0' ><tr>{0}", Chr(10))
            sb.AppendFormat("<td id='MeasureToolbarButton_point' style='border: solid White 1px; background-color: White;' onmouseover='this.style.cursor=""pointer""; this.style.borderColor=""Black"";' onmouseout='checkMeasureToolbarBorder(this, ""point"")' onmousedown='setMeasureToolbarTool(""point"")'><img id='ToolbarImage_point' src='images/measure-point.png' align='middle' alt='Point - Coordinates' title='Point - Coordinates' style='padding: 0px 0px 0px 0px' /></td>{0}", Chr(10))
            sb.AppendFormat("<td id='MeasureToolbarButton_polyline' style='border: solid Black 1px; background-color: #EEEEEE;' onmouseover='this.style.cursor=""pointer"";this.style.borderColor=""Black"";' onmouseout='checkMeasureToolbarBorder(this, ""polyline"")' onmousedown='setMeasureToolbarTool(""polyline"")'><img id='ToolbarImage_polyline' src='images/measure-line.png' align='middle' alt='Line - Distance' title='Line - Distance' style='padding: 0px 0px 0px 0px' /></td>{0}", Chr(10))
            sb.AppendFormat("<td id='MeasureToolbarButton_polygon' style='border: solid White 1px; background-color: White;' onmouseover='this.style.cursor=""pointer"";this.style.borderColor=""Black"";' onmouseout='checkMeasureToolbarBorder(this, ""polygon"")' onmousedown='setMeasureToolbarTool(""polygon"")'><img id='ToolbarImage_polygon' src='images/measure-poly.png' align='middle' alt='Polygon - Area' title='Polygon - Area' style='padding: 0px 0px 0px 0px' />{1}</td>{0}", Chr(10), Chr(9))
            sb.AppendFormat("</tr></table>{0}", Chr(10))
            sb.AppendFormat("<input id='MeasureUnits' type='hidden' value='{0}'/>{1}", MeasureUnits, Chr(10))
            sb.AppendFormat(" <input id='AreaUnits' type='hidden' value='{0}'/>{1}", AreaUnits, Chr(10))
            ' create display area 
            sb.AppendFormat("<table id='MeasureToolbarTable' cellspacing='2' cellpadding='1' style=' width: 100%;font: normal 7pt Verdana; '>{0}", Chr(10))
            sb.AppendFormat("<tr><td style='background-color: #ffffff' id='MeasureDisplay' colspan='2' valign='top'>{0}", Chr(10))
            sb.AppendFormat("Click on the map and draw a line. Double-click to end line.{0}", Chr(10))
            sb.AppendFormat("</td></tr>{0}", Chr(10))
            sb.AppendFormat("</table>{0}", Chr(10))

            Return sb.ToString()
        End Function


        Private Function processPostbackEvent(ByVal requestString As String) As String
            ' break out the responseString into a querystring

            Dim keyValuePairs As Array = requestString.Split("&".ToCharArray())
            Dim m_queryString As New NameValueCollection()
            Dim map As Map = Me.Page.FindControl(Me._mapBuddyId)
            Dim keyValue() As String
            Dim response As String = ""
            If keyValuePairs.Length > 0 Then
                Dim i As Integer
                For i = 0 To keyValuePairs.Length - 1
                    keyValue = keyValuePairs.GetValue(i).ToString().Split("=".ToCharArray())
                    m_queryString.Add(keyValue(0), keyValue(1))
                Next i

            Else
                keyValue = requestString.Split("=".ToCharArray())
                If keyValue.Length > 0 Then
                    m_queryString.Add(keyValue(0), keyValue(1))
                End If
            End If ' isolate control type and mode

            ' isolate control type and mode
            Dim controlType As String = m_queryString("ControlType")
            Dim eventArg As String = m_queryString("EventArg")
            If controlType Is Nothing Then
                controlType = "Map"
            End If

            Select Case controlType
                Case "Map"
                    ' request is for the map control
                    Dim vectorMode As String = m_queryString("VectorMode")
                    If Not (vectorMode Is Nothing) And vectorMode = "measure" Then
                        response = ProcessMeasureRequest(m_queryString)
                    End If
                Case Else
            End Select '
            Return response

        End Function

        Public Sub RaisePostBackEvent(ByVal eventArgument As String) Implements IPostBackEventHandler.RaisePostBackEvent
            Dim strResult As String = processPostbackEvent(eventArgument)
            If Not [String].IsNullOrEmpty(strResult) Then
                ScriptManager.GetCurrent(Me.Page).RegisterDataItem(Me, strResult, False)
            End If
        End Sub

        Public Overrides Property Id() As String '
            Get
                _id = MyBase.ID
                Return MyBase.ID
            End Get
            Set(ByVal value As String)
                _id = value
                MyBase.ID = value
            End Set
        End Property

        Public Property MapBuddyId() As String
            Get
                Return _mapBuddyId
            End Get
            Set(ByVal value As String)
                _mapBuddyId = value
            End Set
        End Property

        Public Property MapUnits() As MapUnit
            Get
                Return _startMapUnits
            End Get
            Set(ByVal value As MapUnit)
                _startMapUnits = value
            End Set
        End Property

        Public Property MeasureUnits() As MeasureUnit
            Get
                Return _measureUnits
            End Get
            Set(ByVal value As MeasureUnit)
                _measureUnits = value
            End Set
        End Property

        Public Property AreaUnits() As AreaUnit
            Get
                Return _areaUnits
            End Get
            Set(ByVal value As AreaUnit)
                _areaUnits = value
            End Set
        End Property

        Public Property NumberDecimals() As Double
            Get
                Return _numberDecimals
            End Get
            Set(ByVal value As Double)
                _numberDecimals = value
            End Set
        End Property

        Public Function GetCallbackResult() As String Implements ICallbackEventHandler.GetCallbackResult
            Return processPostbackEvent(callbackArg)
        End Function


        Public Sub RaiseCallbackEvent(ByVal eventArgument As String) Implements ICallbackEventHandler.RaiseCallbackEvent
            callbackArg = eventArgument
        End Sub
    End Class
End Namespace