scripting and mouse events

Silverlight supports programming JavaScript, which enables you to add interactivity to your content.

This document contains the following sections.

scripting and events

Silverlight enables you to run JavaScript code when an event occurs, such as when an object is loaded or the mouse enters an object. Such a script is called an "event handler". 

To define an event handler, you perform three steps.

  1. In your XAML file, add the following attribute to the object that will trigger your function.

    someEvent="myFunction"

    ...where someEvent is the event to which you want to respond and myFunction is the name of the function that you want to handle the event.

  2. Define the function in your JavaScript file. (For information about setting up a JavaScript file, see Setting up your first files.)

Let's try an example. In Silverlight, all Canvas and shape elements have an event called MouseLeftButtonDown which occurs when you the user pushes the left mouse button down while the mouse pointer is over that element.  Let's write an event handler for that event that uses the JavaScript alert function to create a dialog box.

<Canvas Height="300" Width="300"
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Background="transparent"
   MouseLeftButtonDown="helloworld">
   
  <TextBlock Text="click me"  FontSize="50"/>
</Canvas>
function helloworld() {
    alert("hello world");
}

You don't have to specify parameters when you declare an event handler, but if you do do the first parameter, "sender", is the element that sends the event and the second parameter, "args", is an object that contains data about the event.

setting properties

You can set properties of Silverlight objects using JavaScript. When a property takes a value that is a string or a number, you can set it normally in JavaScript. If the property takes a Silverlight object and it has a type converter, such as a SolidColorBrush, you can set the value using a string. Otherwise, you need to use the createFromXaml method to instantiate a new property value.

The following example registers for the MouseLeftButtonDown event of a Canvas. In the event handler, the sender parameter provides access to the Canvas. The example sets the Background property of the Canvas to red and displays the current value of the its Height property.

<Canvas Width="300" Height="300"
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Background="Transparent"
   MouseLeftButtonDown="changecolor">
   
  <TextBlock Text="click me"  FontSize="50"/>
</Canvas>
function changecolor(sender, args) {
    sender.background = "red";
    
    alert("Height is " + sender.Height);
}

setting attached properties

To set the value of an attached property, such as Canvas.Top, in JavaScript, you use the following syntax.

object["attachedPropertyName"] = value;

....where attachedPropertyName is the name of the attached property you want to set.

The following example sets the Canvas.Top property of a TextBlock to 70 when the left mouse button is pressed.

<Canvas Width="300" Height="300"
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Background="Transparent">
    
  <TextBlock Text="click me"  FontSize="50" 
     MouseLeftButtonDown="changelocation" />
</Canvas>
function changelocation(sender, args) {
    
    sender["Canvas.Top"] = 70;
}

common mouse events

UIElement objects provide a number of different mouse events you can handle:  MouseLeftButtonDown, MouseLeftButtonUp, MouseEnter (raised when the mouse goes over the element), MouseLeave, and MouseMove (raised when the mouse is moved inside the element).  Mouse events have an "args" object that provides the x and y position of the mouse when the event occurred.

The following example uses each of these mouse events to modify the appearance of an Ellipse.

<Canvas
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   
  <Ellipse x:Name="e1" MouseMove="e1Move"
      MouseEnter="e1Enter" MouseLeave="e1Leave"
      MouseLeftButtonDown="e1Down" MouseLeftButtonUp="e1Up"
      Height="100" Width="100" Canvas.Left="80" Canvas.Top="30"
      Stroke="Black" StrokeThickness="10" Fill="LightBlue"/>
</Canvas>
function e1Enter(sender, args) {
    sender.stroke = "red";
}

function e1Leave(sender, args) {
    sender.stroke = "black";
}

function e1Down(sender, args) {
    sender.fill = "Green";
}

function e1Up(sender, args) {
    sender.fill = "LightBlue";
}

function e1Move(sender, args) {
    sender.fill = "yellow";
}

Another very useful event to know about is the Loaded event.  Usually you register for this event with a declaration at the root element, but Loaded can be specified on any UIElement.  The Loaded event provides a good opportunity to apply any last changes as your Silverlight control is displayed. The following example uses a Loaded event handler to change the Fill of an Ellipse from Blue to Red.

<Canvas
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Ellipse Loaded="ellipse_loaded"
     Height="200" Width="200" 
     Canvas.Left="30" Canvas.Top="30"
     Stroke="Black" StrokeThickness="10" Fill="LightBlue"/>
</Canvas>
function ellipse_loaded(sender, args) {
    sender.Fill = "Red";
}

naming objects and retrieving them

The preceding examples used JavaScript event handlers to modify the object that raised the event, but what happens if you want to use methods or set properties of an object other than the sender?  Silverlight elements provide a method called findName that enables you to retrieve child objects.  To use findName to retrieve an object, you must first use the x:Name attribute to give that object a name when you declare it in XAML.

The following example changes the Fill property of an Ellipse when the left mouse button is pressed over its parent Canvas. When the Canvas raises the event, the changeEllipseColor function is called with Canvas as the sender. The function calls sender.findName() to retrieve the object named myEllipse and set its Fill to Red.

<Canvas
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Background="Transparent"
   MouseLeftButtonDown="changeEllipseColor">
    
  <TextBlock Text="click me"  FontSize="50"/>
  <Ellipse x:Name="myEllipse" 
    Height="200" Width="200" 
    Canvas.Left="30" Canvas.Top="80"
    Stroke="Black" StrokeThickness="10" Fill="LightBlue"/>
</Canvas>
function changeEllipseColor(sender, args) {
    sender.findName("myEllipse").Fill = "red";
}

dynamically creating Silverlight objects

You can use the createFromXaml method to create new Silverlight objects in JavaScript. But before you can use the createFromXaml method, you must obtain a reference to a Silverlight control.

  • If you already have a reference to a Silverlight object, you can use the getHost method to return a reference to the control that hosts it.
  • Otherwise, use the document.getElementById method to retrieve it.

The following example creates a new Ellipse object and adds it to a Canvas each time the left mouse button is pressed.

<Canvas Width="300" Height="300"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Background="Transparent"
    MouseLeftButtonDown="createEllipse">
    
  <TextBlock Text="click for circle"  FontSize="40"/>
</Canvas>
function createEllipse(sender, args) {
    
    var slControl = sender.getHost();
    var e = 
        slControl.content.createFromXaml(
            '<Ellipse Height="200" Width="200" Fill="Blue"/>');
    var canvas = sender;
    canvas.children.Add(e);
}

Note that JavaScript requires you to put strings on a single line, unless you combine multiple strings using the + operator.  Also note also the use of both single quotes (') and double quotes (") in the <Ellipse> XAML string; Starting and ending the JavaScript string with single quotes enables you to use double quotes for values in the XAML string.

controlling animations interactively

You can use event handlers can control animations. Assign a name to the Storyboard that you want to control and then you can use its begin, stop, pause, and resume methods to control it interactively. If you don't want the Storyboard to begin automatically, declare it as a resource rather than declaring it inside an EventTrigger.

<Canvas
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   
  <Canvas.Resources>

    <Storyboard x:Name="animation"
      Storyboard.TargetName="e1"
      Storyboard.TargetProperty="(Canvas.Left)">
      <DoubleAnimation RepeatBehavior="Forever" To="300"/>
    </Storyboard>

  </Canvas.Resources>
  
  <Ellipse x:Name="e1" Fill="Black"
      Height="20" Width="20" Canvas.Left="30" Canvas.Top="30">
    <Ellipse.Fill>
      <RadialGradientBrush GradientOrigin="0.75,0.25">
        <GradientStop Color="White" Offset="0.0" />
        <GradientStop Color="Black" Offset="0.5" />        
      </RadialGradientBrush>    
    </Ellipse.Fill>
  </Ellipse>
  
  <Canvas MouseLeftButtonDown="animation_stop" Canvas.Left="20" Canvas.Top="60">
    <Rectangle Stroke="Black" 
       Height="40" Width="40" RadiusX="5" RadiusY="5">
      <Rectangle.Fill>
        <RadialGradientBrush GradientOrigin="0.75,0.25">
          <GradientStop Color="Orange" Offset="0.0" />
          <GradientStop Color="Red" Offset="1.0" />        
        </RadialGradientBrush>
      </Rectangle.Fill>       
    </Rectangle>
    <TextBlock Canvas.Left="5" Canvas.Top="5">stop</TextBlock> 
  </Canvas>
  
  <Canvas MouseLeftButtonDown="animation_pause" 
     Canvas.Left="70" Canvas.Top="60">
    <Rectangle Stroke="Black" 
       Height="40" Width="50" RadiusX="5" RadiusY="5">
      <Rectangle.Fill>
        <RadialGradientBrush GradientOrigin="0.75,0.25">
          <GradientStop Color="Yellow" Offset="0.0" />
          <GradientStop Color="Orange" Offset="1.0" />        
        </RadialGradientBrush>
      </Rectangle.Fill>       
    </Rectangle>
    <TextBlock Canvas.Left="5" Canvas.Top="5">pause</TextBlock> 
  </Canvas>
  
  <Canvas MouseLeftButtonDown="animation_begin" Canvas.Left="130" Canvas.Top="60">
    <Rectangle Stroke="Black" RadiusX="5" RadiusY="5"
       Height="40" Width="50">
      <Rectangle.Fill>
        <RadialGradientBrush GradientOrigin="0.75,0.25">
          <GradientStop Color="LimeGreen" Offset="0.0" />
          <GradientStop Color="Green" Offset="1.0" />        
        </RadialGradientBrush>
      </Rectangle.Fill>
    </Rectangle>
    <TextBlock Canvas.Left="5" Canvas.Top="5">begin</TextBlock> 
  </Canvas>
</Canvas>
function animation_stop(sender, args) {
    sender.findName("animation").stop();
}

function animation_pause(sender, args) {
    sender.findName("animation").pause();
}

function animation_begin(sender, args) {
    sender.findName("animation").begin();
}

using getElementById to retrieve or create objects

When you're writing script that is not triggered by a Silverlight event (such as an HTML event handler), you won't have a sender parameter that can provide access to the findName or getHost methods. In this case, you can use document.getElementById() to find the Silverlight control, then use the control to call the findName method.

The following example uses the document.getElementById() method to find the Silverlight control named ag8. It then uses the control's findName method to retrieve the Silverlight object named myEllipse and changes its fill to red.

<Canvas
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Background="Transparent"
   MouseLeftButtonDown="changeEllipseColor2">
   
  <TextBlock Text="click me"  FontSize="50"/>
  <Ellipse x:Name="myEllipse" 
    Height="200" Width="200" 
    Canvas.Left="30" Canvas.Top="80"
    Stroke="Black" StrokeThickness="10" Fill="LightBlue"/>
</Canvas>
function changeEllipseColor2() {
    var sl8 = document.getElementById("sl8");
    sl8.content.findName("myEllipse").fill = "red";

}

In the previous example, sl8 is the ID of the Silverlight control you created in your host HTML file when you called Sys.Silverlight.createObject(), as described in the part 1: create a Silverlight project document.


        // Retrieve the div element you created in the previous step.
        var mySilverlightControlHost = document.getElementById("sl8Host");
        createMySilverlightControl();

        Sys.Silverlight.createObject(
             "sl8.xaml", 
             sl8Host, 
             "sl8",
             {
                  width:'300', 
                  height:'300', 
                  inplaceInstallPrompt:false, 
                  background:'#D6D6D6', 
                  isWindowless:'false', 
                  framerate:'24', 
                  version:'0.8'},
             {onError:null, onLoad:null},
             null);