SoftMemes SoftMemes - 1 year ago 51
Javascript Question

How can I pass a JavaScript function to Silverlight?

I'm evaluating the JavaScript/Silverlight interop capabilities and have been able to create a Silverlight instance using JavaScript and call methods on it. However, I now need a way of passing a JavaScript callback function to Silverlight.

Simply passing a JavaScript function to a Silverlight method expecting an Action doesn't work although the error suggest that it's intended to. What am I missing? The exception details:

Microsoft JScript runtime error: System.ArgumentException: Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.
at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure)
at System.Windows.Hosting.ScriptingInterface.GetDelegateForScriptObject(Type eventHandlerType, ScriptObject obj)
at System.Windows.Browser.ScriptObject.ConvertTo(Type targetType, Boolean allowSerialization)
at System.Windows.Hosting.ScriptingInterface.GetScriptParamValueForType(ScriptParam scriptParam, Type desiredType)
at System.Windows.Hosting.ScriptingInterface.ConvertFromScriptParams(ParameterInfo[] parameters, ScriptParam[] args)
at System.Windows.Browser.ManagedObjectInfo.ScriptMethod.Invoke(ManagedObject obj, InvokeType invokeType, ScriptParam[] args)
at System.Windows.Browser.ManagedObjectInfo.Invoke(ManagedObject obj, InvokeType invokeType, String memberName, ScriptParam[] args)
at System.Windows.Hosting.ManagedHost.InvokeScriptableMember(IntPtr pHandle, Int32 nMemberID, Int32 nInvokeType, Int32 nArgCount, ScriptParam[] pArgs, ScriptParam& pResult, ExceptionInfo& pExcepInfo)

Answer Source

Without seeing your code I cannot say what you are doing wrong but I can describe what has worked for me in the past.

On the Silverlight side you need to register a class as a scriptable object. Then create a method that is marked as a ScriptableMember and takes a string that will be your passed in JavaScript method. I also added a method called InvokeCallback which will invoke the passed in javascript callback.

public partial class Page : UserControl
    private string jsCallback;
    public Page()
        HtmlPage.RegisterScriptableObject("silverlightInterop", this);

    public void RegisterCallback(string callback)
      jsCallback = callback;

    public boid InvokeCallback(string arg)
          System.Windows.Browser.HtmlPage.Window.Invoke(jsCallback, arg);

On the JavaScript side you can call the RegisterCallback method that you defined in Silverlight by grabbing the silverlight object on the page and calling the method off of the name "silverlightInterop" which we registered as the name of our scriptable object.

function jsCallback(someArg) {

var silverLightControl = document.getElementById("silverlightControl");

I hope this helps. I also have some sample code the demonstrates this which I wrote a while ago here