我们知道,Siverlight 作为 浏览器的一个插件,就相当于程序的容器,那么我们怎样和Html 中的JS 代码交互呢,其实微软给我们了解决方案. 参考文章http://www.cnblogs.com/HellenTian/archive/2010/11/11/1874711.html
1.Silverlight 来调用Javascript 。比如我想显示两个Map 一个Map 是Silverlight API 来写,另一个Map 用 JS API来写.实现两个Map的联动效果。当我 SL中的Map的Extent的发生变化时,JS中MAP 相应也变化到相同的Extent。
我们可以在JS 文件里写一个 jssetextent 函数来来对MAP的Extent进行 设置,在SIlverlight中进行调用。首先我在我的HTMl页面如下:
- <span style="font-size:18px;"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>JSANDSLAPI</title>
- <style type="text/css">
- html, body
- {
- height: 100%;
- overflow: auto;
- }
- body
- {
- padding: 0;
- margin: 0;
- }
- #silverlightControlHost
- {
- height: 100%;
- text-align: center;
- }
- #jsdiv
- {
- height: 80%;
- width: 45%;
- float: left;
- background-color: #3FC;
- }
- </style>
- <link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/3.2/js/dojo/dijit/themes/claro/claro.css"/>
- <link rel="stylesheet" type="text/css" href="http://serverapi.arcgisonline.com/jsapi/arcgis/3.2/js/esri/css/esri.css" />
-
- <script type="text/javascript" src="Silverlight.js"></script>
- <script src="Scripts/jquery-1.4.1.min.js" type="text/javascript"></script>
- <script type="text/javascript"> var djConfig = { parseOnLoad: true };</script>
- <script type="text/javascript" src="http://serverapi.arcgisonline.com/jsapi/arcgis/?v=3.2"></script>
-
- <script type="text/javascript">
- function onSilverlightError(sender, args) {
- var appSource = "";
- if (sender != null && sender != 0) {
- appSource = sender.getHost().Source;
- }
-
- var errorType = args.ErrorType;
- var iErrorCode = args.ErrorCode;
-
- if (errorType == "ImageError" || errorType == "MediaError") {
- return;
- }
-
- var errMsg = "Unhandled Error in Silverlight Application " + appSource + "\n";
-
- errMsg += "Code: " + iErrorCode + " \n";
- errMsg += "Category: " + errorType + " \n";
- errMsg += "Message: " + args.ErrorMessage + " \n";
-
- if (errorType == "ParserError") {
- errMsg += "File: " + args.xamlFile + " \n";
- errMsg += "Line: " + args.lineNumber + " \n";
- errMsg += "Position: " + args.charPosition + " \n";
- }
- else if (errorType == "RuntimeError") {
- if (args.lineNumber != 0) {
- errMsg += "Line: " + args.lineNumber + " \n";
- errMsg += "Position: " + args.charPosition + " \n";
- }
- errMsg += "MethodName: " + args.methodName + " \n";
- }
-
- throw new Error(errMsg);
- }
-
- </script>
- <script type="text/javascript">
- dojo.require("dijit.layout.BorderContainer");
- dojo.require("dijit.layout.ContentPane");
- dojo.require("esri.map");
- var map; function init() {
- var initExtent = new esri.geometry.Extent({ "xmin": -27141257.7092732, "ymin": -31127629.9353227, "xmax": 27141257.7092732, "ymax": 31127629.9353228, "spatialReference": { "wkid": 102100} });
- map = new esri.Map("jsdiv", {
- extent: esri.geometry.geographicToWebMercator(initExtent)
- });
-
- var basemap = new esri.layers.ArcGISTiledMapServiceLayer("http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer");
- map.addLayer(basemap);
-
- dojo.connect(map, 'onLoad', function (theMap) {
-
- dojo.connect(dijit.byId('map'), 'resize', map, map.resize);
- });
-
-
- } dojo.addOnLoad(init);
-
-
- function jssetextent(xmin, xmax, ymin, ymax) {
-
- var myextent = new esri.geometry.Extent({ "xmin": parseFloat(xmin), "ymin": parseFloat(ymin), "xmax": parseFloat(xmax), "ymax": parseFloat(ymax), "spatialReference": { "wkid": 102100} });
-
- map.setExtent(myextent);
- }
- </script>
- </head>
- <body>
- <div style="float: left; height: 80%; width: 50%; background-color: #036">
- <form id="form1" runat="server" style="height: 100%; width: 100%; background-color: #036">
- <div id="silverlightControlHost">
- <object id="SLContainer" data="data:application/x-silverlight-2," type="application/x-silverlight-2"
- width="100%" height="100%">
- <param name="source" value="ClientBin/JSANDSLAPI.xap" />
- <param name="onError" value="onSilverlightError" />
- <param name="background" value="white" />
- <param name="minRuntimeVersion" value="5.0.61118.0" />
- <param name="autoUpgrade" value="true" />
- <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=5.0.61118.0" style="text-decoration: none">
- <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight"
- style="border-style: none" />
- </a>
- </object>
- <iframe id="_sl_historyFrame" style="visibility: hidden; height: 0px; width: 0px;
- border: 0px"></iframe>
- </div>
- </form>
- </div>
- <div id="jsdiv">
- </div>
- </body>
- </html>
- </span>
以上代码中<div id="silverlightControlHost"> 来作为Silverlgiht插件的容器。为 <object id="SLContainer" data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">增加一个id属性,方便JS 获取。<div id='jsdiv'> 来作为我们的JS API 的MAP的容器,并且包含了初始化MAP 并添加了一个缓存图层。红色部分 是一个定义好的函数,接受四个参数,主要功能是设置MAP的Extent ,这个函数是在后面的 Siverlight 中来调用的
在 SL中的XAML的代码如下
- <span style="font-size:18px;"><Grid x:Name="LayoutRoot" Background="White">
- <esri:Map Background="Beige" Name="SLmap" PanDuration="0" ExtentChanged="SLmap_ExtentChanged">
- <esri:Map.Layers>
- <esri:LayerCollection>
- <esri:ArcGISTiledMapServiceLayer Url="http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" />
- </esri:LayerCollection>
- </esri:Map.Layers>
- </esri:Map>
- </Grid></span>
用System.Windows.Brower命名空间下的某些silverlight类,你可以调用一段脚本写的javascript函数。这样就给你的silverlight代码一个很有规律的方式来和页面交互。
- <span style="font-size:18px;"></span>
- <span style="font-size:18px;"> private void SLmap_ExtentChanged(object sender, ESRI.ArcGIS.Client.ExtentEventArgs e)
- {
-
- double xmin = SLmap.Extent.XMin;
- double xmax = SLmap.Extent.XMax;
- double ymin = SLmap.Extent.YMin;
- double ymax = SLmap.Extent.YMax;
- ScriptObject scriptObjcet = (ScriptObject)HtmlPage.Window.GetProperty("jssetextent");
- scriptObjcet.InvokeSelf(xmin, xmax, ymin, ymax);
-
- }</span>
通过 HTml Page .Window .GetProperty 来 获取这个函数,剩下的就是就是传递参数然后调用了 运行的效果如下,当平移或者缩放左侧的Map时,右侧Map的范围也会发生改变
2,以上已经实现了再 SIlverlight 中调用 JS中的函数,下面开始实现一个在JS代码中来调用 SL中的函数,以实现JS与SL的互操作,我实现在 JS API中MAP中增加一个点, 然后把点的坐标传递到SL 里面来,在Sl中MAP的相同位置增加一个 点
在javascript中调用silverlight方法,主要有以下步骤:
在silverlight程序中创建一个公开的方法来暴露你想在web页面中用的函数。
在方法上边添加一个ScriptableMember属性。
在包含这个方法的类上添加ScriptableType属性。
调用HtmlPage.RegisterScriptableObject()将这个方法暴露给javascript。
在 Silverlight 的XAML 文件中为MAP添加一个GraphisLayer ,并编写为此Graphicslayer添加点的代码 C#代码如下
- [ScriptableType]
- public partial class MainPage : UserControl
- {
- public MainPage()
- {
- InitializeComponent();
- HtmlPage.RegisterScriptableObject("JSOBJ", this);
- }
-
- [ScriptableMember]
- public void Addpoint(double ptx ,double pty)
- {
-
- MapPoint pt = new MapPoint(ptx, pty);
- SimpleMarkerSymbol makersymbol = new SimpleMarkerSymbol();
- makersymbol.Style = SimpleMarkerSymbol.SimpleMarkerStyle.Square;
- makersymbol.Size = 10;
- Graphic g = new Graphic();
- g.Geometry = pt;
- g.Symbol = makersymbol;
- GraphicsLayer glayer = SLmap.Layers["MyGraphicslayer"] as GraphicsLayer;
- glayer.Graphics.Add(g);
-
-
- }
为 方法所在的类以及该方法增加特性,同时将该方法所在的实例注册为JSOBJ,允许外部的JS代码可以调用 Sl内部的方法。
下面再JS文件里编写代码,在 map的点击事件里为Map 增加一个函数,增加一个graphic 同时获取AddPoint方法并调用,同时把点的坐标传递给Addpoint作为参数。
- dojo.connect(map, "onClick", function (evt) {
-
- var symbol1 = new esri.symbol.SimpleMarkerSymbol(esri.symbol.SimpleMarkerSymbol.STYLE_SQUARE, 10, new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, new dojo.Color([255, 0, 0]), 1), new dojo.Color([0, 255, 0, 0.25]));
- var graphic = new esri.Graphic(evt.mapPoint, symbol1);
- map.graphics.add(graphic);
-
- var slcontainer = document.getElementById("SLContainer");
- slcontainer.content.JSOBJ.Addpoint(evt.mapPoint.x, evt.mapPoint.y);
-
- });
其中最后两行为获取承载Silverlight的 Object对象,然后获取刚才注册的JSOBJ,并调用Addpoint方法。运行程序,在JS MAP中鼠标点击,会发现 Silverlight中MAP中相同位置也会增加相应的点。说明我们已经完成了 在JS中调用 Silverlight的方法。结果如下;
以上只是简单的介绍了 使用Silverlight 与javascript的交互操作,证明了技术的可行性。为我们开发GIS应用提供了新的选择,让我们更方便的使用这些技术的,充分发挥Silverlight或者JS的优点,当然可以结合更多的空间分析。。
demo下载地址