======================================================
注:本文源代码点此下载
======================================================
silverlight与html页面的交互功能是通过统称为html bridge的一组类型和方法来实现的。要启用交互功能需要在创建silverlight控件时指定enablehtmlaccess参数为true,否则很多方法的使用都会引发异常。
在object标签式创建方法中为:
param name="enablehtmlaccess" value="true" />
silverlight直接控制html
在silverlight中可以使用system.windows.browser命名空间中的类和方法来操作html,主要涉及以下几个类:
browserinformation - 代表浏览器及客户端操作系统相关信息
htmldocument - 代表浏览器中的html文档
htmlelement - 代表了一个html元素
htmlpage - 提供了操作dom的方法
htmlwindow - 代表javascript中的window
其中,最重要的就是htmlpage类,它提供了一组静态方法来获取其他类的实例,如:
取得browserinformation:
browserinformation browserinfo = htmlpage.browserinformation;
取得htmldocument:
htmldocument htmldocument = htmlpage.document;
取得htmlwindow:
htmlwindow htmlwindow = htmlpage.window;
下面列举一些常用操作:
在新窗口中打开网页:
htmlpage.window.navigate(new uri("https://www.google.com"), "__blank");
修改页面标题:
htmlpage.document.setproperty("title", "new title");
修改、取得页面元素属性:
htmlelement elem = htmlpage.document.getelementbyid("elem1");
elem.setattribute("value", "haha");
string value = elem.getattribute("value");
注册html元素事件:
elem.attachevent("onclick", delegate(object sender, htmleventargs he)
{
// ...
});
javascript中调用silverlight方法/属性
要从javascript中调用silverlight方法,silverlight必须首先注册scriptableobject。这可以通过给要暴露给js的类型加上scriptabletypeattribute,这样就会暴露该类型的所有属性、方法和事件;如果只要暴露一部分成员,也可以仅给这一部分成员标记scriptablememberattribute(在过去的版本中仅有scriptableattribute)。这个标记是非常宽松的,只要类中有成员是scriptable的,就可以使用htmlpage.registerscriptableobject方法来注册这个类使其能被js访问。比如:
public partial class mainpage : usercontrol{public mainpage(){initializecomponent();htmlpage.registerscriptableobject("page", this);}[scriptablemember]public string process(string arg){return "called from js: " + arg;
}
}
在html页面则可以用如下js代码调用process方法:
function callsl() {var slhost = document.getelementbyid("silverlightcontrol");var page = slhost.content.page;alert(page.process('param from js'));}
将callsl方法注册到按钮的onclick上:
input type="button" value="call sl" onclick="callsl()" />
点击运行结果如下:
silverlight属性的调用方法同理。
(附带一提,这里的"silverlightcontrol"是silverlight控件的id,即silverlight的object标签id。)
javascript注册silverlight中的事件
无参数事件
silverlight中,事件用scriptablememberattribute标记或者包含事件的类用scriptabletypeattribute标记后,再用htmlpage.registerscriptableobject注册该类,在javascript中就可以访问该事件。比如silverlight暴露如下事件:
public event eventhandler buttonclicked;
那么在js中可以用下面的代码注册该事件:
function onsilverlightload() {var slhost = document.getelementbyid("silverlightcontrol");var page = slhost.content.page;page.buttonclicked = function () {alert("button clicked in sl.");};
}
那么当用户点击silverlight中的按钮时,就会执行注册的js代码:
值得注意的是,这段js并不能放在页面的onload事件中执行,因为那时silverlight控件可能还没加载完成,应该放在silverlight控件的onload事件中。在silverlight的标签中添加onload参数:
param name="onload" value="onsilverlightload" />
带参数事件
然后是如何传递事件参数的问题,网上许多人说指定自定义参数时,在js中无法获取,提示不支持指定的方法或属性,其实只要将eventargs类本身也指定为scriptabletype即可(当然也可将成员指定为scriptablemember)。示例如下。
事件参数类:
[scriptabletype]public class buttonclickedeventargs : eventargs{public string message { get; set; }}
mainpage类:
public partial class mainpage : usercontrol{
…
private void button_click(object sender, system.windows.routedeventargs e){
// 引发buttonclicked事件并传入事件参数onbuttonclicked(new buttonclickedeventargs() { message = "message from sl." });}#region [buttonclicked event][scriptablemember]public event eventhandlerbuttonclickedeventargs> buttonclicked;[system.diagnostics.debuggerstepthrough]protected virtual void onbuttonclicked(buttonclickedeventargs e){if(null != buttonclicked){buttonclicked(this, e);}}#endregion}
将js的事件处理函数改成:
page.buttonclicked = function (sender, args) {alert(args.message);};
如此,当点击sl中按钮时结果如下:
可见event args被成功传递了出来。
under the hood
至此基本已满足一般使用的需要了。其实不论是从js调用silverlight方法/属性,或者注册silverlight事件,其本质问题都是如何将托管对象传给javascript,这里面就有一个对象marshal的问题。marshal遵循以下原则:
托管类型通过传递引用的方式传给javascript
javascript类型要传入silverlight,必须要先进行一层托管的封装
如果将托管类型marshal到javascript过程发生错误,抛出invalidoperationexception
如果将javascript数据marshal入silverlight时发生错误,javascript调用者将得到一个异常,异常文本描述了发生的错误
基本类型(即所谓的primitive types)
以下类型属于基本类型,即不需要标记scriptabletypeattribute或者scriptablememberattribute而可以直接在silverlight和js之间传递的类型:
silverlight
javascript
string
字符串
null
null
boolean
boolean
datetime
date
char
单字符的字符串
数字类型
double(来回转换可能引发精度及溢出问题)
枚举
数字
guid
格式化的字符串
除此之外,基本的c#数组或者实现了ilist接口的类型,可以直接转换为javascript中的array;实现了idictionary的类型也可以直接转为javascript中的dictionary。
反过来,javascript中的数组传入silverlight时,一般会被转为object[];dictionary则被转为dictionary.
复杂类型
对于用户创建的复杂类型,则需要通过标记scriptabletypeattribute或者scriptablememberattribute,使其能够正确地传递给javascript.
对于silverlight和javascript间的marshal,以上依然只描述了各种最基本的情形。我也不想做那种照翻msdn的事情,对于更加复杂的情形,以及各种注意事项,可自行参考silverlight and javascript marshaling。
http://silverlightchina.net/html/tips/2010/0709/1466.html
======================================================
在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定 这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/