QUICKSTARTS
[This topic is pre-release documentation and is subject to change in future releases of Microsoft Silverlight.]

scripting and mouse events

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, follow 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.)

Now 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.  You will 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 do not have to specify parameters when you declare an event handler function. But if you do specify parameters, the first parameter, sender, is the element that sends the event. The second parameter, args, is an object that contains data about the event. However, not all events will transmit specific event information in args; often the value of that parameter is null and is not useful for your event handler.

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 or Point, 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, which you will typically reference in handlers for mouse events.

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 for Silverlight programming is the Loaded event. Usually you register handlers for this event with a declaration at the root element, but Loaded can be specified on any UIElement, not just the root. The Loaded event provides a good opportunity to apply any last changes as your Silverlight content 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 Silverlight objects from any frame of reference within the Silverlight content. To use FindName to retrieve an object, you must first specify the x:Name attribute (or the Name attribute/property, which is essentially equivalent) 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 plug-in instance.

  • If you already have a reference to any Silverlight object, you can use the GetHost method to return a reference to the plug-in instance that hosts it.
  • Otherwise, use the document.getElementById method to retrieve the plug-in instance.

The following example creates a new Ellipse object and adds it to a Canvas each time the left mouse button is pressed. Note that although you are adding multiple objects if you click more than once, you will see only one ellipse. That is because all the ellipses look exactly alike, and are drawing on top of each other.

<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 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, or vice versa. Just make sure the single and double quotes balance correctly.

dynamically creating Silverlight objects, with XAML string manipulation

The previous example showed one potentially undesirable side effect of adding the same XAML to the page more than once. If you do want to add objects with XAML, it is often desirable to change that XAML in some way each time. You can do that by adjusting the XAML string immediately before each call.

The following example creates a new Ellipse object and adds it to a Canvas each time the left mouse button is pressed, but this time three properties of the Ellipse will change each time so that you can see that there really are multiple objects being added to the page.

<Canvas Width="300" Height="300"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Background="Transparent"
    MouseLeftButtonDown="createEllipse2">
    
  <TextBlock Text="click for Lots of circles"  FontSize="20"/>
</Canvas>
var opacitychange = 1;
var canvastop = 0;
var canvasleft = 0;
function createEllipse2(sender, args) {
    
    var slControl = sender.getHost();
    xamlstring = '<Ellipse Height="10" Width="10" Fill="Red"';
    xamlstring += " Opacity = '" + (opacitychange-=0.1) + "'";
    xamlstring += " Canvas.Left = '" + (canvasleft+=15) + "'";
    xamlstring += " Canvas.Top = '" + (canvastop+=15) + "'";
    xamlstring += "/>";
    var e = slControl.content.createFromXaml(xamlstring);
    var canvas = sender;
    canvas.children.Add(e);
}

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 do not 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"
      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 are writing script that is not triggered by a Silverlight event (such as an HTML event handler), you will not 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 plug-in, then use the Silverlight plug-in object to call the FindName method.

The following example uses the document.getElementById() method to find the Silverlight plug-in instance named sl9. It then uses FindName method to retrieve the Silverlight plug-in instance 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 sl9 = document.getElementById("sl9");
    sl9.content.findName("myEllipse").fill = "red";

}

In the previous example, sl9 is the HTML DOM ID of the Silverlight plug-in instance you created in your host HTML file when you called Silverlight.createObject(), as described in the part 1: create a Silverlight project document.


        // Retrieve the div element you created in the previous step.
        var mySilverlightPluginHost = document.getElementById("sl9Host");
        createMySilverlightPlugin();

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


what's next

The next topic, sample controls, describes how to compose basic controls.

Page view counter