Making Silverlight Scriptable by JavaScript

Microsoft Silverlight will reach end of support after October 2021. Learn more.

When you host a Silverlight-based application within a Web page, you can include JavaScript code in the page that interacts with your Silverlight-based code. This enables you to use Silverlight to extend the capabilities of JavaScript or JavaScript to extend the capabilities of Silverlight.

The following topic explains how to use JavaScript to access properties, methods, and events defined in a Silverlight-based application. This topic contains the following sections:

  • Marking Types and Members as Scriptable

  • Attaching JavaScript Methods to Scriptable Managed Events

  • Properties of Type EventHandler

  • ScriptEventHandler Class API

  • Special Support for ASP.NET AJAX

NoteNote:

Silverlight for Windows Phone Silverlight for Windows Phone does not support the HTML Bridge feature.

Marking Types and Members as Scriptable

Silverlight-based applications can specify members in public types that should automatically be made available to JavaScript in the containing page. Input parameters, return values, and event arguments for properties and methods follow the rules described in the Returning or Passing Managed Types to JavaScript topic.

The following example shows how to mark properties, events, and methods as scriptable by using the ScriptableMemberAttribute attribute.

public class MyStockWatcher
{
    [ScriptableMemberAttribute]
     public string SomeProperty {get; set;}

    [ScriptableMemberAttribute]
    public event EventHandler SomeEvent;

    [ScriptableMemberAttribute]
   public string DoWork(int count);
 }

You can explicitly register an instance of a scriptable type with the runtime by using the RegisterScriptableObject(String, Object) method.

Registration can occur in the App class, the Page class, classes connected to the App or Page class by namespace, or in managed event handlers, as the following code demonstrates.

public CustomCanvas : Canvas
{
    public static void Canvas_Loaded(object o, EventArgs e)
    {
        MyStockWatcher m = new MyStockWatcher();
        HtmlPage.RegisterScriptableObject("stockwatcher", m);
    }
}

As soon as you register an instance of a scriptable type, JavaScript code can access the scriptable members of that type by using the Content property of the Silverlight plug-in object.

Registration of a managed instance is explicit; therefore, you are not required to attribute the class definition with ScriptableTypeAttribute, although it is acceptable for you to do so. Additionally, type definitions that are used as input parameters or return values on properties and methods of a scriptable instance do not have to be marked as ScriptableMemberAttribute.

Event properties also have a somewhat relaxed constraint for the event argument type. The HtmlEventArgs class is automatically supported for scriptable event properties. Derived event argument types do not have to be attributed with ScriptableTypeAttribute, because the base event argument type is already scriptable. However, if you want additional properties on the custom event argument type to be marshaled back to JavaScript, those properties must be attributed with ScriptableMemberAttribute. Otherwise, the event argument will be null in JavaScript.

The general rules for marking types as scriptable are as follows:

  • Scriptable types must be public types.

  • For a property, method, or event to be accessible to JavaScript, it must be public and marked as scriptable with the ScriptableMemberAttribute.

  • For code optimization, you can attribute a class with ScriptableTypeAttribute. This means that all public properties, methods, and events on that type automatically become accessible to JavaScript.

    NoteNote:

    This behavior applies only to the members of the specific type on which the ScriptableTypeAttribute was applied. It does not apply to inherited members or members of derived types. For example, if class Scriptable_B derives from class BaseClass_A, only the members of Scriptable_B are accessible from script. In addition, if class Derived_C derives from class Scriptable_B, the inherited members from class Scriptable_B class are scriptable. To make non-inherited members of class Derived_C scriptable, specify the ScriptableMemberAttribute on each desired member.

  • Scriptable event properties must be of type EventHandler or EventHandler<TEventArgs>, or derivations of these. Currently, the scriptable feature does not support using arbitrary delegates in scriptable events.

If you try to return a .NET Framework type to JavaScript or pass a complex .NET Framework type as an input parameter to Invoke(String, array<Object[]), InvokeSelf(array<Object[]), or SetProperty, and that type has no scriptable members, Silverlight will not throw an exception. However, it will create a stub JavaScript object without any callable properties, methods, or events.

Attaching JavaScript Methods to Scriptable Managed Events

Managed event properties (that is, properties with the event keyword) that are marked with ScriptableMemberAttribute can have JavaScript methods set directly on them. However, this results in a maximum of one event handler per managed event property.

The HTML Bridge adds the JavaScript method set to the delegate list of the managed event property by using the equality (=) operator. From the managed code perspective, using the equality operator (=) from JavaScript is really a combined (+=) operation. The equality operator only sets the default handler for the event.

If you need to create a chain of event handlers, you must use the addEventListener syntax instead.

To support multiple event listeners, Silverlight also inserts the following event subscription methods into the scripting interface that is exposed by the registered script object:

addEventListener(string eventName, object JavaScriptMethod);
removeEventListener(string eventName, object JavaScriptMethod);

The JavaScriptMethod that is added to the event delegate chain is also used to un-register the JavaScript method from the delegate chain.

Properties of Type EventHandler

You can write a public [ScriptableMemberAttribute] property that is of type EventHandler. Although this is not a recommended practice, the HTML Bridge does support it.

The following code example shows a scriptable OnClick property.

[ScriptableMemberAttribute]
public EventHandler OnClick
{
    get { return _onClick; }
    set { _onClick = onClick;}
}

You can assign a JavaScript function to this property so that JavaScript code can call it, as shown in the following example.

myScriptableObject.OnClick = function() {alert("Click");};
myScriptableObject.OnClick();

You can also round-trip this property back to managed code, which can also trigger the event, as shown in the following example.:

// Assumes this is the same application domain.
EventHandler EVH1= (EventHandler)HtmlPage.Plugin.GetProperty("OnClick");
EVH1 ();

See Returning or Passing Managed Types to JavaScript for specific rules for round-tripping event delegates.

ScriptEventHandler Class API

ASP.NET AJAX behaviors and controls have a common event signature: The first parameter is a reference to the ASP.NET AJAX control or behavior that raised the event and the second parameter is an arbitrary complex type. The ScriptEventHandler class supports this event signature as follows:

namespace System.Windows.Browser
{
    public delegate void ScriptEventHandler(ScriptObject sender, 
                                             ScriptObject args);
}

Special Support for ASP.NET AJAX

For interoperability with ASP.NET AJAX, the following JavaScript properties, methods, and events are automatically added to scriptable endpoints:

// Adds a constructor property that returns a generic Function object.
    .constructor