********************************************************************
* 著作權聲明
*
* 本文以Creative Commons的發布,請嚴格遵循該授權協議。
* 本文首發於部落格園, 此聲明為本文章中不可或缺的一部分。
* 作者網名: 浪子
* 作者EMAIL:dayichen (at)163.com
* 作者BLOG: Http://Www.Cnblogs.Com/Walkingboy
*
********************************************************************
[Silverlight探秘]深入探索Silverlight與Javascript的互動
-Written by 浪子@cnblogs.com (07-07-01)
摘要
在[Silverlight探秘]利用Javascript調用silverlight的方法和[Silverlight探秘]利用Silverlight調用Javascript的方法中,大概的學習了兩者之間如何進行簡單的互動,但是兩次探索中都遺留了些問題,本文對這些問題進行了深入的嘗試,在這個過程中學習理解兩者之間的更深入更複雜的互動情境。
本文環境
- Codename Orcas Beta1
- Silverlight 1.1 Alpha
- IE 6.0
問題一、Javascript調用Silverlight的方法獲得的傳回值支援什麼類型的?對於複雜類型如何處理?
在[Silverlight探秘]利用Javascript調用silverlight的方法中,我提出了這個疑問,silverlightfans兄認為為複雜的類型貼上Scriptable的標籤即可支援將其序列化為javascript的對象。在我試用scriptable的時候,我也這樣子認為,於是我做了如下嘗試:
[Scriptable] public MyClass ReturnClass(){return new MyClass() { Name = "walkingboy", Blog = "http://walkingboy.cnblogs.com"};}
[Scriptable]public class MyClass{[Scriptable]public string Name{get;set;}[Scriptable]public string Blog{get;set;}public DateTime BirthDay { get; set; }}
不幸的是,如果你真的這樣子做,將會得到如下錯誤資訊
---------------------------
Microsoft Internet Explorer
---------------------------
Silverlight error message
ErrorCode: 1001
ErrorType: ParserError
Message: AG_E_UNKNOWN_ERROR
XamlFile: Page.xaml
Line: 9
Position: 27
可見silverlight並不能自動轉換一個複雜的類型到javascript類型上。在網上查閱了一些資料,原來silverlight目前還只支援序列化一些普通的類型(字串、數字、數組等),我把這些普通類型理解為javascript內建的類型。
那如何解決我們的複雜物件返回呢?還好silverlight內建了對json的支援,我們可以直接將複雜物件序列化為json格式的字串,然後在javascript進行還原序列化,就像我們現在開發ajax應用中的一樣。
silverlight的json序列化支援類包含在Microsoft.Silverlight.dll下的System.Windows.Browser.Serialization命名空間中。
JavaScriptSerializer jss = new JavaScriptSerializer();//json序列化string json = jss.Serialize(instance);//json還原序列化MyClass instance = jss.Deserialize<MyClass> (json);
此類的功能跟asp.net ajax中的類基本類似,可以參考相關的資料(如Jeffrey Zhao的深入Atlas系列:探究序列化與還原序列化能力)。
問題二、Silverlight調用Javascript方法是否可以返回指定的型別參數?
經過上面的測試,我甚至擔心這個問題也只能通過json序列化來解決。為了測試這個問題,我寫了如下的測試代碼
[Scriptable]public class MyEventArgs : EventArgs{public MyEventArgs(){}[Scriptable]public string Message{get;set;}}
定義好了自訂的EventArgs之後,按照[Silverlight探秘]利用Silverlight調用Javascript的方法中的方法,設定一個Scriptable的Event
[Scriptable]public event EventHandler<MyEventArgs> ReturnArgs;
測試結果運行正常,於是想是否支援有傳回值的委託呢?
public delegate string ReturnCustomerEventArgsEventHandler(MyEventArgs args);[Scriptable]public event ReturnCustomerEventArgsEventHandler ReturnArgs;
照樣運行起來之後得到如下錯誤
---------------------------
Microsoft Internet Explorer
---------------------------
Silverlight error message
ErrorCode: 1001
ErrorType: ParserError
Message: AG_E_UNKNOWN_ERROR
XamlFile: Page.xaml
Line: 9
Position: 27
看來不能用此種方式擷取javascript的運行傳回值。
綜合
其實感覺有點奇怪,即然Silverlight可以通過Event傳遞一個自訂類型的參數給javascript方法,為什麼javascript調用Silverlight方法反而不行?原則上兩者其實是一樣的。我想不同在於一個是“推”,一個是“拉”,期待正式版中能內嵌支援返回自訂類型的結果值,就省去自己序列化的麻煩了。
結合一下上面的兩個互動情境,其實跟ajax的實現情境有點類似了,我覺得完全可以通過silverlight替代現有的ajax方法,當然這個後面我會進一步去測試。
BTW:如果你的類中沒有一個方法,屬性,事件貼有Scriptable,而你在構造器中調用
WebApplication.Current.RegisterScriptableObject("LangZi", this);
則你將得到一個解析錯誤
---------------------------
Microsoft Internet Explorer
---------------------------
Silverlight error message
ErrorCode: 2210
ErrorType: ParserError
Message: AG_E_INVALID_ARGUMENT
XamlFile: Page.xaml
Line: 10
Position: 72
測試代碼:ScriptableAdvance.rar
廢話一句,MS的Blend真是不咋地:(