Silverlight Interop 6-傳遞ManagedObject

先前示範過將JS端的物件傳入Silverlight,現在來逆向操作,把Managed Type傳回JS世界!

宣告一個ColumnSetting類別,其中特別設一個列舉(ColumnTypeEnum)觀察它的傳換結果。另外,宣告兩個函數: SL2JS()傳回ColumnSetting,JS2SL(ColumnSetting)傳入ColumnSetting當參數。

        //欄位型別列舉
        public enum ColumnTypeEnum
        {
            TextBox, NumericTextBox,
            ComboBox, Checkbox, DatePicker
        }
        //記得要加註ScritableType, 要用Property不能用Field
        [ScriptableType]
        public class ColumnSetting
        {
            public string Name { get; set; }
            public ColumnTypeEnum ColumnType { get; set; }
            public int Width { get; set; }
            public ScriptObject OnCellEdit { get; set; }
        }
 
        //傳ColumnSetting到JS端,注意ColumnType傳的是其整數值
        [ScriptableMember]
        public ColumnSetting SL2JS()
        {
            ColumnSetting cs = new ColumnSetting()
            {
                Name = "Amount",
                ColumnType = ColumnTypeEnum.NumericTextBox,
                Width = 100
            };
            return cs;
        }
        [ScriptableMember]
        public void JS2SL(ColumnSetting cs)
        {
            if (IsFunction(cs.OnCellEdit))
                cs.OnCellEdit.InvokeSelf("Callback");
            MessageBox.Show(cs.Width.ToString());
        }

在Javascript端,我們做幾個測試:

  1. 用SL2JS()以cs變數接回ColumnSetting物件
  2. 用cs.Name, cs["Width"]嘗試讀取其值,而列舉cs.ColumnType傳回其整數值1
  3. 用for (var p in cs)測試,可發現它不像一般純Javascript Object可以列舉出屬性,骨子裡它還算是SL中的物件,只是外面再包覆(Marshaling)一層包裝,盡量模擬JS Object的行為而已。
  4. 用先前介紹過的InvokeSelf技巧,可以傳入函數供Silverlight端呼叫。
  5. 修改cs.Width後,再將同一元件當成參數傳入JS2SL(),Silverlight端可以再取得Managed Type讀取修改過的值。
function onSilverlightLoad(sender, args) {
 
    var slCtl = sender.getHost();
    var jssk = slCtl.Content.JavascriptSidekick;
    
    //由SL端取得Managed物件
    var cs = jssk.SL2JS();
    alert(cs.Name); //正常
    alert(cs.ColumnType); //enum,會傳回其值=1
    alert(cs["Width"]); //用[colName]也成
    
    //得到的東西並非純Javascript物件
    try {
        var sb = [];
        for (var p in cs) 
        {
            sb.push(p + "->" + cs[p]);
        }
        //故無法用for (var p in csRefTest)列舉, 
        //IE:sb.length=0 FF:Error
        alert(sb.length);     
    } catch(err) {
        alert("Error:" + err);
    }
    
    //修改內容再傳回去
    //設定回Call事件
    cs.OnCellEdit = function(s) {
        alert("Hello, " + s);
    };
    //修改數值
    cs.Width = 200;
    jssk.JS2SL(cs);
}

那我們可不可以從{ Name:"...", ColumnType:.. }自已捏一個Javascritp物件轉型成ColumnSetting呢? 答案是不行! 即使所有屬性取的名字一模一樣,Javascript物件無法直接轉型成Managed Type。

若要在JS端生成可轉型成Managed Type的物件,可透過createObject()或createManagedObject(),createManagedObject因不需事先RegisterScritableType,使用起來較方便,請參考以下的例子。

    //改用JS端從無到有建立物件
    var jscs = { 
        Name:"UnitPrice", ColumnType:1, Width:300 };
    jssk.JSD2SL(jscs);
    
    //以上的寫法是行不通的,會發生轉型錯誤
    //This object cannot be converted to the specified type 
    //'JsInterop.JavascriptSidekick+ColumnSetting'.        
 
    //要建立可當參數傳入的Managed Object,改用createManagedObject()
    jscs = jssk.createManagedObject("ColumnSetting");
    jscs.Name="UnitPrice";
    jscs.ColumnType=1;
    jscs.Width=365;
    jssk.JS2SL(jscs);

下回再來看另一個有趣的問題,By Value or By Reference?

歡迎推文分享:
Published 06 May 2010 08:10 AM 由 Jeffrey
Filed under: ,
Views: 7,124



意見

沒有意見

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<May 2010>
SunMonTueWedThuFriSat
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345
 
RSS
創用 CC 授權條款
【廣告】
twMVC

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication