我们知道,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页面如下:
<!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>
以上代码中<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的代码如下
<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>
用System.Windows.Brower命名空间下的某些silverlight类,你可以调用一段脚本写的javascript函数。这样就给你的silverlight代码一个很有规律的方式来和页面交互。
private void SLmap_ExtentChanged(object sender, ESRI.ArcGIS.Client.ExtentEventArgs e)
{
// string s=SLmap.Extent
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);
}
通过 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下载地址