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,會傳回其值=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?
Comments
Be the first to post a comment