Reputation: 1993
I'm developing a Silverlight4 drop-in replacement for an existing Flash client. I would like to maintain compatibility with the existing Flash HTML bridge javascript functions, but I can't figure out how to expose the javascript interface directly on the Silverlight client object instead of a contained object.
In Flash, it is possible to call Bar() directly on the client object, as in:
var flashClient = document.GetElementById(_currentFlashId);
flashClient.Bar();
But in Silverlight, I haven't found a means to call an interface directly on the Silverlight object. Instead, it appears interfaces can only be exposed on contained objects, as in:
var silverlightClient = document.GetElementById(_currentSilverlightId);
silverlightClient.Foo.Bar();
Where the "Foo" object above seems to be required, since
RegisterScriptableObject("Foo", MyFooObject);
can't be called with a null first parameter.
So, in Silverlight, is there any way to just have just:
silverlightClient.Bar();
?
Upvotes: 2
Views: 216
Reputation: 4818
There is a bit of a laborious way of doing this (I'm in the same situation -- trying to drop a direct Silverlight replacement of a Flash app).
For every [ScriptableMember]
, call the BackBind method, with number of parameters after calling HtmlPage.RegisterScriptableObject("Foo", MyFooObject);
BackBind method:
void BackBind(string methodName, int argCount) {
var id = HtmlPage.Plugin.Id;
var sb = new StringBuilder();
sb.Append("var x = document.getElementById('");
sb.Append(id);
sb.Append("'); x.");
sb.Append(methodName);
sb.Append(" = function(");
for (int i = 0; i < argCount; i++) {
if (i > 0) sb.Append(',');
sb.Append((char)('A' + i)); // if you have more than 26 arguments, improve this!
}
sb.Append("){return x.content.");
sb.Append(ScriptRegistration);
sb.Append(".");
sb.Append(methodName);
sb.Append("(");
for (int i = 0; i < argCount; i++) {
if (i > 0) sb.Append(',');
sb.Append((char)('A' + i)); // if you have more than 26 arguments, improve this!
}
sb.Append(");};");
HtmlPage.Window.Eval(sb.ToString());
// calls something like: var x = document.getElementById('my_id'); x.Bar = function(a,b){return x.content.Foo.Bar(a,b);};
}
Usage example:
public class MyFooObject {
const string ScriptRegistration = "Foo";
public MyFooObject () {
HtmlPage.RegisterScriptableObject(ScriptRegistration, this);
BackBind("Bar", 2);
BackBind("Baz", 0);
}
[ScriptableMember]
public void Bar(string a, int b) { /* stuff */ }
[ScriptableMember]
public string Baz() { return "stuff"; }
}
Hope that helps!
Upvotes: 0
Reputation: 78860
If you're just wanting an object with a compatible interface, you could just do this:
var silverlightClient = document.GetElementById(_currentSilverlightId).Foo;
Upvotes: 1