Handling Silverlight Events by Using JavaScript

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

Silverlight provides a managed API. But you can also choose to continue to use the JavaScript API that was initially supported by Silverlight 1.0. This includes using JavaScript as the language that is used to write event handlers for Silverlight events, as well as performing other code operations.

This topic contains the following sections.

  • Adding an Event Handler in XAML
  • Programming Models and Event Handler Lookup
  • Event Model Features That Are Common to Managed and JavaScript
  • Writing Event Handlers in JavaScript
  • Adding Event Handlers in JavaScript
  • JavaScript HTML DOM Events and Loaded/onload
  • Related Topics

Adding an Event Handler in XAML

The following XAML example shows how to add a handler for the Loaded event on a Canvas object. Notice that the event-handler function cannot be called with parameter values (even empty ones), which is unlike JavaScript event-handler functions for HTML elements in the HTML DOM.

<Canvas Loaded="OnLoaded" />

At the element level in XAML, there is no difference in how you reference the handler between the managed API and the JavaScript API. In both cases, you provide a string that names an event handler function (or method).

Programming Models and Event Handler Lookup

If the x:Class attribute exists, this corresponds to the page and larger application using the managed API. In this case, lookup for the event handler goes to the class referenced as x:Class. If the x:Class attribute does not exist, the page cannot be markup-compiled, there is no code-behind partial class (or at least the XAML parser cannot determine what the class is), and the page must use the JavaScript API for event handling. In this case, the host evaluates scripting in its scripting engine against the available JavaScript function and object definitions at run time in the HTML DOM.

Event Model Features That Are Common to Managed and JavaScript

Whether using the managed API or the JavaScript API, event handler functions/methods share the following concepts in their signatures: a sender value and an eventArgs (event data) value. The meaning of sender in both models is that sender is the object where the event handler is attached. The event data in both models is some object that has properties (and sometimes methods) that report specifics of that particular occurrence of the event.

Both models support the Silverlight implementation of a routed event. A routed event is an event that originates with one object in a tree of objects, but is then routed (forwarded) to each successive parent in the object tree and potential handlers on that parent, until that event reaches the root of the object tree. Generally, the object tree representation of how an event routes through the tree is analogous to the nesting of XAML object elements in the XAML that defines the page. The routed event concept in Silverlight is the reason why the definition of sender as the object where the event handler is attached differs from sender definitions you might see in basic .NET Framework documentation about CLR events, where sender is the object that raised the event. That is not necessarily true in a routed event case; the event might have been raised by a child object in the object tree and routed upwards. This routed event concept is also sometimes discussed in Silverlight and WPF documentation as being a bubbling event.

Writing Event Handlers in JavaScript

The following JavaScript example shows how to define a Silverlight event-handler function. In this case, the code displays a string in an alert dialog box that calls toString() on the sender parameter, which can be a useful debugging technique for determining information about objects.

function onLoaded(sender, eventArgs)
{
    // Display the object type of the sender parameter.
    alert("Sender = " + sender.toString());
}

JavaScript Optional Parameters and eventArgs

A JavaScript event handler does not need to specify any parameters. There is no delegate concept that binds the handler to a particular signature or convention, and instead event handlers are a prototype. If your handler has no need for either sender or eventArgs, you can omit them from the handler signature.

In many Silverlight events, the value of eventArgs available to a JavaScript handler is null, so there is no benefit in referencing the event data from a handler.

However, for some events, the event data in eventArgs is as important as knowing that the event was raised. This is particularly true of the input events. For mouse events, the position of the mouse when the event occurred might be important, and can be determined using the GetPosition method called from the eventArgs. For keyboard events, keys on the keyboard raise the same KeyUp and KeyDown events, so in order to determine which key was pressed you must access the KeyboardEventArgs that are available to the event handler. It is a good practice to use more specific naming of the second parameter of event handler functions whenever a specialized set of event data is available for that event. For this example, the handler prototype might use keyboardEventArgs instead of the less specific eventArgs. The event data type as well as properties within it that are available to a handler for a Silverlight event are noted in the reference for each event.

If you are specifically using the JavaScript API, you can use event system features that also exist in the managed API to stop a route. The event data class for a routed event often has a Handled property. Setting Handled to true in the event data will stop the routing behavior in the event system, such that only the first object that handles the routed event will receive it. A Handled property is available on the MouseButtonEventArgs and KeyboardEventArgs objects, which are available for handlers on mouse-button events or keyboard events, respectively. Event data for mouse, keyboard, and focus events also has a Source property, which reports the object that raised the event as opposed to where the event is handled (sender).

Accessing the Silverlight Object Tree by Combining sender and FindName

You can reference named Silverlight objects other than the sender in an event-handler function, if they can be retrieved by a name that was established in the initial XAML. To name the object in XAML so that you can reference it later in script, use the x:Name attribute to declare the object's name in the object tree. The name applies as soon as the XAML is loaded and parsed and the object representation is created, so typically you wait until some event is handled (either Loaded or some specific UI event). Then, typically by using the provided sender as the entry point into the general Silverlight object tree, you can call FindName on sender and reference the named object in the extended object tree. The following XAML creates an object tree with a named TextBlock, and an event handler on the parent Canvas.

<Canvas
  xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
  Loaded="onLoaded">

  <TextBlock x:Name="myTextBlock" />

</Canvas>

The following JavaScript example shows how to use the FindName method to search the Silverlight object tree for a specific named object. In this case, the code displays the current date as the Text property of the TextBlock object.

function onLoaded(sender, eventArgs)
{
    // Set the TextBlock to display the current date and time.
    sender.findName("myTextBlock").text = Date();
}

Adding Event Handlers in JavaScript

In addition to adding handlers to objects through the initial XAML, you can also add handlers to objects at run time.

To add and remove event-handler functions for Silverlight objects in JavaScript, use the AddEventListener and RemoveEventListener methods. The following JavaScript example shows how to add events to a TextBlock object.

function onLoaded(sender, eventArgs)
{
    textBlock = sender.findName("Status");
    var entertoken1 = textBlock.addEventListener("MouseEnter", onMouseEnter);
    var leavetoken1 = textBlock.addEventListener("MouseLeave", onMouseLeave);
}

In the preceding example, you might have noticed the "token" return values. In some circumstances, you might want to remove event handlers. You might do this if you intend to replace a previously added event handler with a different handling function. To remove an existing event-handler function, use the RemoveEventListener method. The following JavaScript example shows how to remove event handlers for two different events from a TextBlock object.

function removeEvents()
{
    textBlock.removeEventListener("MouseEnter", entertoken1);
    textBlock.removeEventListener("MouseLeave", leavetoken1);
}

Notice how the remove event handler code references the named tokens that were declared as variables in the add event handler code. The tokens are really just integer values. The tokens are returned by the AddEventListener calls because it might be necessary to differentiate handlers if there was more than one handler defined for the same event on the same instance. If you do not intend to remove handlers later, you do not have to store the return value tokens when you call AddEventListener.

You can also remove handlers for cases where the event was added through a XAML event attribute. In the XAML event attribute case, there was no function call that could return a token. However, you can supply the value 0 (zero) for the token parameter to remove an event where the handler was added using a XAML attribute. The tokens represent the order that handlers were added, starting from 0 and counting up. Because the XAML attribute handlers are the first handlers added (parsing of XAML happens before any script can add handlers), and because there can only be one event handler added per event/instance using XAML, a XAML-added event handler's token value is always 0.

NoteNote:

The Gecko DOM supports a DOM method on many elements that is also named AddEventHandler and has a similar conceptual purpose. The Gecko DOM version can be distinguished from the Silverlight AddEventHandler because the Gecko DOM version has three parameters and the Silverlight version has two. You cannot use the Gecko DOM version of AddEventHandler to add handlers for objects in the Silverlight object tree. However, you could use it to add handlers to any elements in your HTML page that are truly in the HTML DOM.

JavaScript HTML DOM Events and Loaded/onload

JavaScript provides a set of events that you can use to respond to changes on the Web page. For example, the following HTML example shows JavaScript code that is triggered by the JavaScript HTML DOM onload event.

<body onload='javascript:alert("onload event generated")'>

In this example, JavaScript code is defined inline, instead of referencing an event-handler function. This is not possible with Silverlight events; you must define and reference functions.

Also, note the name similarity between the onload HTML DOM event, and the Silverlight Loaded. The HTML DOM onload event is not raised until the entire Web page is loaded. This means that any Silverlight plug-in contained within the page raises its Loaded event before the HTML DOM onload event.

Error Events

Errors in the JavaScript API can often be handled by writing a handler for OnError that is defined for the Silverlight plug-in object. Error events always include event data in the form of ErrorEventArgs that are available to the error handler, and parser and run-time events provide the specialized subclasses ParserErrorEventArgs or RuntimeErrorEventArgs respectively.