脚本和鼠标事件

显示目录表

Silverlight 支持 JavaScript 编程,这允许你给你的内容添加交互性。

本文档包含以下章节。

脚本和事件

当一个事件发生时,Silverlight 允许你运行 JavaScript 代码, 比如当一个对象被读取或者鼠标进入一个对象。 这样一个脚本被称作 "event handler".

要定义一个 event handler,遵照如下三步。

  1. 在你的 XAML 文件中,添加如下的属性到对象,这将触发你的函数。

    someEvent="myFunction"

    这里 someEvent 是你想响应的事件, myFunction 是你想要处理事件的函数的名称。

  2. 在你的 JavaScript 中定义函数。 (关于设置 JavaScript 的信息,请参见 设置你的第一个文件。)

现在试一下示例。在 Silverlight 中, 所有 Canvas 和形状元素都有一个叫 MouseLeftButtonDown 的事件, 当鼠标指针在元素上时你(用户)按下鼠标左键触发该事件。 你将写一个事件函数,使用 JavaScript 的 alert 函数创建一个对话框。

<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");
}

当你声明一个事件处理函数时,你没有一个明确的参数。 但如果你指明参数,第一个参数,sender, 是传递事件的元素。 第二个参数,args, 是一个包含事件数据的对象。 但是,不是所有的事件都会在 args 中传递明确的信息; 通常参数值是 null 这对你的事件处理来说是没有用的。

设置属性

你可以使用 JavaScript 设置 Silverlight 对象的属性。 当一个属性的值是字符串或数字,你可以在 JavaScript 中像平常一样设置。 如果属性是 Silverlight 对象,就需要类型转换, 比如一个 SolidColorBrushPoint, 你可以使用一个字符串来设置值。 否则,你需要使用 createFromXaml 方法来实例化一个新的属性值。

下面的示例注册 CanvasMouseLeftButtonDown 事件。 在事件处理中,sender 参数提供访问 Canvas。 示例设置 CanvasBackground 属性为红色并显示当前 Height 属性的值。

<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);
}

设置附加属性

要为附加属性设置值,比如 Canvas.Top,在 JavaScript 中, 你使用下面的语法。

object["attachedPropertyName"] = value;

这里attachedPropertyName 是你想要设置的附加属性的名称。

下面的示例当鼠标左键按下时设置一个 TextBlockCanvas.Top 属性为 70。

<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;
}

常用鼠标事件

UIElement 对象提供许多不同的鼠标事件供你处理: MouseLeftButtonDownMouseLeftButtonUpMouseEnter(当鼠标移入元素时触发)、 MouseLeaveMouseMove(当鼠标在元素内移动时触发)。 当事件发生时鼠标事件有一个“args”对象提供鼠标位置的 x 和 y, 一般你将在鼠标事件处理中引用。

下面的示例使用这里每一个鼠标事件来修改 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";
}

对 Silverlight 来说,另一个非常有用事件是 Loaded 事件。 通常你在根元素声明中注册该事件处理, 但 Loaded 可以在任意 UIElement 中标明, 不只是根元素。 Loaded 事件提供一个好的机会接收 Silverlight 内容显示后的任何最后改变。 下面的示例使用一个 Loaded 事件处理来改变一个 EllipseFillBlueRed.

<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";
}

给对象命名并取回

前面的示例使用 JavaScript 事件处理来改变触发事件的对象, 但是,如果你使用对象的方法或设置其属性而不是 sender,将会发生什么? Silverlight 元素提供一个叫 FindName 的方法, 这样你可以从 Silverlight 内容的任何框架引用中取得 Silverlight 对象。 要使用 FindName 来取得对象, 当你在 XAML 中声明对象时,你必须首先标明 x:Name 属性(或 Name 特性/属性,本质上来说二者是相同的)以给对象一个名字。

下面的示例当在父级 Canvas 中按下鼠标左键时,改变了 EllipseFill 属性。 当 Canvas 触发事件时, changeEllipseColor 函数被调用,Canvas 是 sender。 函数调用 sender.findName() 取得名为 myEllipse 的对象, 并设置其 FillRed

<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";
}

动态创建 Silverlight 对象

你可以使用 CreateFromXaml 在 JavaScript 中创建一个新的 Silverlight 对象。 但是当你使用 CreateFromXaml 方法之前, 你必须获得 Silverlight 插件实例的引用。

下面的示例每次鼠标左键按下时创建一个新的 Ellipse 对象并将其添加到一个 Canvas。 注意,虽然你点击多次会添加多个对象,但你只会看到一个椭圆, 那是因为所有的椭圆看起来都完全一样,并且绘画在其它椭圆的上面。

<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);
}

注意,JavaScript 要求你将字符串放在一行, 除非你使用 + 操作符将多个字符串连接起来。 同时注意,在 <Ellipse> XAML 字符串中可以使用引号(')和双引号(")。 在 JavaScript 字符串中开始和结束使用单引号时允许你使用双引号作为 XAML 字符串的值, 反过来也是一样的。只是确保单引号和双引号平衡正确。

使用 XAML 字符串处理动态创建 Silverlight 对象

当多次添加同样的 XAML 到页面时,前面的示例展示潜在着不合适的效果。 如果你真的想要使用 XAML 添加对象, 通常每次通过一些方法改变 XAML 是较合适的。 你可以在每次调用前通过立即调整 XAML 字符串来实现。

下面的示例每次鼠标左键按下时创建一个新的 Ellipse 对象并添加到一个 Canvas, 但这回,每次创建时 Ellipse 的三个属性将会改变, 以便你可以真正的看到多个对象被添加到页面中了。

<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);
}

控制动画交互

你可以使用事件处理来控制 animations。 给你想要控制的 Storyboard 添加名字, 然后你可以使用它的 beginStopPauseResume 方法来控制其交互性。 如果你不想让 Storyboard 自动开始, 将其声明为一个资源,而不是在 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();
}

使用 getElementById 方法获得和创建对象

当你在写不被 Silverlight 事件(比如一个 HTML 事件处理)触发的脚本时, 你将不会有 sender 参数提供 FindNameGetHost 方法的访问。 在这种情况下, 你可以使用 document.getElementById() 来找到 Silverlight 插件, 然后使用 Silverlight 插件对象来调用 FindName 方法。

下面的示例使用了 document.getElementById() 方法来查找名为 sl9 的 Silverlight 插件实例。 它使用 FindName 方法取得名为 myEllipse 的 Silverlight 插件实例, 并改变它的 Fill 为红色。

<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);


下一步是什么

下一个主题,示例控件,描绘了如何编写基础控件。