Silverlight Interop 6-傳遞ManagedObject
| | | 0 | |
先前示範過將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端,我們做幾個測試:
- 用SL2JS()以cs變數接回ColumnSetting物件
- 用cs.Name, cs["Width"]嘗試讀取其值,而列舉cs.ColumnType傳回其整數值1
- 用for (var p in cs)測試,可發現它不像一般純Javascript Object可以列舉出屬性,骨子裡它還算是SL中的物件,只是外面再包覆(Marshaling)一層包裝,盡量模擬JS Object的行為而已。
- 用先前介紹過的InvokeSelf技巧,可以傳入函數供Silverlight端呼叫。
- 修改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,會傳回其值=1alert(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:Erroralert(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?
Comments
Be the first to post a comment