ArcGIS Mapping Extension (in progress)

JS-Support @Userware
Site Admin
Posts: 1142
Joined: Tue Apr 08, 2014 3:42 pm

ArcGIS Mapping Extension (in progress)

Postby JS-Support @Userware » Wed Feb 24, 2016 11:53 am

This extension requires CSHTML5 v1.0 Beta 7.2 or newer.

It lets you use the ArcGIS mapping library in your CSHTML5 application. It wraps the JavaScript-based library into a C#/XAML-based control that can be consumed in C# and XAML.


To use, simply add a new class named "Map.cs" to your project, and copy/paste the following code:

Code: Select all

using CSHTML5;
using ESRI.ArcGIS.Client.Geometry;
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;


//--------------------------------
// This is a C#/XAML wrapper around the ArcGIS JavaScript library.
// It makes it possible to use the ArcGIS JavaScript API in a CSHTML5 project.
// The namespaces, classes, and methods mimic the Silverlight API so that developers who
// are migrating their Silverlight apps to HTML/JS can do so without having to make changes
// to their code, by simply referencing this wrapper DLL in a CSHTML5 project.
// This project is meant to be compiled using CSHTML5 v1.0 Beta 7.2 or newer (more info: cshtml5.com)
// The reference for the Silverlight API that this project attempts to mimic is available at:
// https://developers.arcgis.com/silverlight/api-reference/#library-reference-overview.html
//
// This project is licensed under The open-source MIT license:
// https://opensource.org/licenses/MIT
// Copyright 2016 Userware / CSHTML5 (C#/XAML for HTML5)
//--------------------------------


namespace ESRI.ArcGIS.Client
{
    /// <summary>
    /// Represents a Map control with a set of service layers that can be navigated using mouse and keyboard controls.
    /// Reference: https://developers.arcgis.com/silverlight/api-reference/#ESRI.ArcGIS.Client~ESRI.ArcGIS.Client.Map.html
    /// </summary>
    public class Map : Canvas
    {
        object _map; // Keeps a reference to the JavaScript "map" object.
        private double _zoom = 3;

        /// <summary>
        /// Constructor.
        /// </summary>
        public Map()
        {
            this.Loaded += ArcGISMapControl_Loaded;
            this.Unloaded += ArcGISMapControl_Unloaded;
        }

        #region Private members

        /// <summary>
        /// Happens when the control is loaded into the Visual Tree.
        /// </summary>
        async void ArcGISMapControl_Loaded(object sender, RoutedEventArgs e)
        {
            // Get a reference to the HTML DOM representation of the control (must be in the Visual Tree):
            object div = Interop.GetDiv(this);

            // Make sure that the Div has an ID, because the ArcGIS map controls requires an ID:
            Interop.ExecuteJavaScript("if (!$0.id) { $0.id = $1 }", div, Guid.NewGuid().ToString());

            // Load the ArcGIS libraries and CSS files:
            await Interop.LoadJavaScriptFile("http://js.arcgis.com/3.13/");
            await Interop.LoadCssFile("http://js.arcgis.com/3.13/esri/css/esri.css");

            // Render the ArcGIS map:
            Interop.ExecuteJavaScript(@"
var divId = $0.id;
var onClick = $1;
var methodToRememberJavaScriptMapObject = $2;
var zoom = $3;
require([""esri/map"", ""dojo/domReady!""], function(Map) {
    var map = new Map(divId, {
        center: [-56.049, 38.485],
        zoom: zoom,
        basemap: ""streets""
    });
    methodToRememberJavaScriptMapObject(map);
    map.on('click', onClick);
    });
", div, (Action<object>)OnClick, (Action<object>)MethodToRememberJavaScriptMapObject, _zoom);
        }

        /// <summary>
        /// Happens when the control is unloaded from the Visual Tree.
        /// </summary>
        void ArcGISMapControl_Unloaded(object sender, RoutedEventArgs e)
        {
            // We release the reference to the Map object so that other code (such as "SetZoom") will not refresh the Map:
            _map = null;
        }

        /// <summary>
        /// This callback is called by the JavaScript initialization code so as to keep a reference to the JS map object in the C# context.
        /// </summary>
        /// <param name="map"></param>
        void MethodToRememberJavaScriptMapObject(object map)
        {
            _map = map;
        }

        /// <summary>
        /// Happens when the user clicks on the map.
        /// </summary>
        /// <param name="args"></param>
        void OnClick(object args)
        {
            if (MouseClick != null)
            {
                object jsMapPoint = Interop.ExecuteJavaScript("$0.mapPoint", args);
                MouseClick(this, new MouseEventArgs()
                {
                    MapPoint = MapPoint.CreateFromJavaScript(jsMapPoint)
                });
            }
        }

        #endregion

        #region Public methods

        /// <summary>
        /// Sets the map zoom level to the given value.
        /// </summary>
        /// <param name="zoom">The zoom level.</param>
        public void SetZoom(double zoom)
        {
            _zoom = zoom;

            if (_map != null)
                Interop.ExecuteJavaScript("$0.setZoom($1)", _map, zoom);
        }

        #endregion

        #region Public events

        /// <summary>
        /// The event handler that determines when the left mouse click has occurred in the Map Control.
        /// Reference: https://developers.arcgis.com/silverlight/api-reference/#ESRI.ArcGIS.Client~ESRI.ArcGIS.Client.Map~MouseClick_EV.html
        /// </summary>
        public event EventHandler<Map.MouseEventArgs> MouseClick;

        #endregion

        #region Public nested classes

        /// <summary>
        /// Mouse event arguments.
        /// Reference: https://developers.arcgis.com/silverlight/api-reference/#ESRI.ArcGIS.Client~ESRI.ArcGIS.Client.Map_MouseEventArgs.html
        /// </summary>
        public class MouseEventArgs
        {
            /// <summary>
            /// Gets or sets the point on the map where the event was raised
            /// Reference: https://developers.arcgis.com/silverlight/api-reference/#ESRI.ArcGIS.Client~ESRI.ArcGIS.Client.Map_MouseEventArgs~MapPoint.html
            /// </summary>
            public MapPoint MapPoint { get; set; }
        }

        #endregion
    }
}

namespace ESRI.ArcGIS.Client.Geometry
{
    public class MapPoint
    {
        public double X { get; set; }
        public double Y { get; set; }

        public static MapPoint CreateFromJavaScript(object jsMapPoint)
        {
            var mapPoint = new MapPoint()
            {
                X = Convert.ToDouble(CSHTML5.Interop.ExecuteJavaScript("$0.x", jsMapPoint)),
                Y = Convert.ToDouble(CSHTML5.Interop.ExecuteJavaScript("$0.y", jsMapPoint))
            };
            return mapPoint;
        }
    }
}


You can test the code by creating a new XAML page and using the following XAML code:

Code: Select all

<Page
    ...
    xmlns:esriclient="using:ESRI.ArcGIS.Client">

    <esriclient:Map MouseClick="Map_MouseClick"/>
   
</Page>

and C# code:

Code: Select all

void Map_MouseClick(object sender, ESRI.ArcGIS.Client.Map.MouseEventArgs e)
{
    MessageBox.Show("X: " + e.MapPoint.X.ToString() + "   Y: " + e.MapPoint.Y);
}


In the Simulator you will notice a JavaScript warning when loading the map, and 2 warnings when clicking on the map. But you can safely ignore those warnings, as they won't appear in the final version when running in the browser.

Regards,
JS-Support

labbr01
Posts: 6
Joined: Fri Jul 17, 2015 10:20 am

Re: ArcGIS Mapping Extension (in progress)

Postby labbr01 » Fri May 13, 2016 11:12 am

I am trying to switch ArcGIS API version from 3.13 to 4.0 (no longer beta version, but official one).

I am not able to display a map with API 4.0 using C#Xaml.

According to ESRI, creating a 2D Map with API 4.0 is similar (Html Page to display a map)
------- Begin HTML -----
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<title>Get started with MapView - Create a 2D map</title>
<style>
html, body, #viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<link rel="stylesheet" href="https://js.arcgis.com/4.0/esri/css/main.css">
<script src="https://js.arcgis.com/4.0/"></script>

</head>
<body>
<script>
require([
"esri/Map",
"esri/views/MapView",
"dojo/domReady!"
], function(Map, MapView){
var map = new Map({
basemap: "streets"
});
var view = new MapView({
container: "viewDiv", // Reference to the scene div created in step 5
map: map, // Reference to the map object created before the scene
zoom: 4, // Sets the zoom level based on level of detail (LOD)
center: [15, 65] // Sets the center point of view in lon/lat
});
});
</script>
<div id="viewDiv"></div>
</body>
</html>
------- END HTML-----

When i traduce this HTML into a C#XAML .cs control, this is written this way:
---- BEGIN C# -----
/// <summary>
/// Happens when the control is loaded into the Visual Tree.
/// </summary>
async void ArcGISMapControl_Loaded(object sender, RoutedEventArgs e)
{
// Get a reference to the HTML DOM representation of the control (must be in the Visual Tree):
object div = Interop.GetDiv(this);

// Make sure that the Div has an ID, because the ArcGIS map controls requires an ID:
Interop.ExecuteJavaScript("if (!$0.id) { $0.id = $1 }", div, Guid.NewGuid().ToString());

//Version 4.0 de ArcGIS
//Load the ArcGIS libraries and CSS files:
await Interop.LoadJavaScriptFile("https://js.arcgis.com/4.0/");
await Interop.LoadCssFile("https://js.arcgis.com/4.0/esri/css/main.css");

Interop.ExecuteJavaScript(@"
var divId = $0.id;
var methodToRememberJavaScriptMapObject = $1;
var zoom = $2;
require([
""esri/Map"",
""esri/views/MapView"",
""dojo/domReady!""
], function (Map, MapView) {
var map = new Map({
basemap: ""streets""
});
var view = new MapView({
container: divId, //reference to the scene div created in step 5
map: map, //reference to the map object created before the scene
zoom: zoom, //sets the zoom level based on level of detail (LOD)
center: [15, 65] //sets the center point of view in lon/lat
});
methodToRememberJavaScriptMapObject(view);
});
", div, (Action<object>)MethodToRememberJavaScriptMapObject, _zoom);

////// //Previous code for version 3.13 de ArcGIS
////// // Load the ArcGIS libraries and CSS files:
////// await Interop.LoadJavaScriptFile("http://js.arcgis.com/3.13/");
////// await Interop.LoadCssFile("http://js.arcgis.com/3.13/esri/css/esri.css");

////// // Render the ArcGIS map:
////// Interop.ExecuteJavaScript(@"
////// var divId = $0.id;
////// var onClick = $1;
////// var methodToRememberJavaScriptMapObject = $2;
////// var zoom = $3;
////// require([""esri/map"", ""dojo/domReady!""], function(Map) {
////// var map = new Map(divId, {
////// center: [-56.049, 38.485],
////// zoom: zoom,
////// basemap: ""streets""
////// });
////// methodToRememberJavaScriptMapObject(map);
////// map.on('click', onClick);
////// });
////// ", div, (Action<object>)OnClick, (Action<object>)MethodToRememberJavaScriptMapObject, _zoom);

}
---- END C# -----

With api 4.0, it's seem three is no map control. A saw with fiddler a request to get the definition of the EsriService, but no other call to get the tiles from street map.

JS-Support @Userware
Site Admin
Posts: 1142
Joined: Tue Apr 08, 2014 3:42 pm

Re: ArcGIS Mapping Extension (in progress)

Postby JS-Support @Userware » Sun May 15, 2016 9:03 pm

Thanks. We are going to look into the v4 API.

Regards


Return to “Extensions and Plugins for CSHTML5”

Who is online

Users browsing this forum: No registered users and 3 guests