Silverlight中鼠标事件的js开发

     在silverlight 中,我们可以通过js事件绑定方法addEventListener,往xaml文件中的UIElement
元素上绑定事件js事件,也可以通过直接属性赋值的方法来将事件绑定到UIElement元素上,比如下面
的语法声明:
  

<Rectangle x:Name="" MouseEnter="onMouseEnter"  />

     本人比较喜欢前者的定义方法,主要是因为其灵活性和支持prototype式的代码结构。下面就通过
一个获取鼠标当前坐标位置的例子,来说明一下如果使用js事件绑定。

     首先我们需要定义一个Silverlight JScript 文件,并将其命名为MoveScene.xaml,如下图所示:



     这时系统会生成两个文件,一个是同名的MoveScene.xaml,而另一个就是其绑定的js文件:
MoveScene.js。我们可以将相应的代码放入这两个文件中,其中xaml代码如下:

<Canvas xmlns="http://schemas.microsoft.com/client/2007"
        xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
        Width
="300" Height="300" x:Name="rootCanvas" Background="pink">

  
<Ellipse x:Name="MouseEllipse"
    Height
="100" Width="100" 
    Canvas.Left
="30" Canvas.Top="30" Fill="Red"/>

  
<TextBlock x:Name="Status" Canvas.Top="140" MouseLeftButtonDown="onMouseLeftButtonUp" />
</Canvas>

    上面代码中定义了两个元素:
     1. Ellipse元素, 名称为:MouseEllipse, 该元素将会绑定鼠标事件。
     2. TextBlock元素,名称为:Status,该元素会显示当前鼠标在MouseEllipse元素中的位置。
    
    下面就是关于鼠标事件绑定的代码(因系统已为我们生成了一个简单的初始化代码,我们仅需放
入相应的事件绑定代码即可),取终代码结构如下(MoveScene.js):

 

Silverlight_JsWeb.MoveScene = function() 
{
}

Silverlight_JsWeb.MoveScene.prototype 
=
{

 handleLoad: 
function(plugIn, userContext, rootElement) 
 {
     
this.plugIn = plugIn;
  
  
// 按钮事件挂钩示例: 查找按钮,然后附加事件处理程序
  var MouseEllipse = rootElement.findName("MouseEllipse"); 
  
  MouseEllipse.addEventListener(
"MouseMove", Silverlight.createDelegate(thisthis.handleMouseMove));
  
  MouseEllipse.addEventListener(
"MouseLeave", Silverlight.createDelegate(thisthis.handleMouseLeave));
  
  MouseEllipse.addEventListener(
"MouseLeftButtonUp", Silverlight.createDelegate(thisthis.handleMouseLeftButtonUp));
 },
 
 
// 鼠标移入处理程序
 handleMouseMove: function(sender, mouseEventArgs)
    {
        sender.Fill 
= "Coral";    
    
        
var currX = mouseEventArgs.getPosition(null).x;
        
var currY = mouseEventArgs.getPosition(null).y;

        
var Status = sender.findName("Status");
        Status.Text 
= "x:" + currX + " y:" + currY;
          
    },
    
    
// 鼠标离开处理程序
    handleMouseLeave: function(sender, mouseEventArgs)
    {
        sender.Fill 
= "Teal";
    },
    
    
// 鼠标左键单击处理程序
    handleMouseLeftButtonUp: function(sender, mouseEventArgs)
    {
        sender.Fill 
= "Blue";
        alert(
"x:" +mouseEventArgs.getPosition(null).x + 
             
" y:" +mouseEventArgs.getPosition(null).y);
    }
}

     这里面有两个方法需要着重介绍一下:
     addEventListener 该方法用于向指定的元素绑定相应的方法。其函数声明如下:  

object.AddEventListener(eventName, functionReference)

    其参数:
    eventName表示事件的名称,string类型(如KeyDown等)。
    functionReference ,表示事件处理方法的引用,Object类型(通常采用Silverlight.createDelegate方法创建)。

    该方法的使用已如上面代码所声明的那样:    

MouseEllipse.addEventListener("MouseMove", Silverlight.createDelegate(thisthis.handleMouseMove));

    这样我们就将handleMouseMove方法绑定到了MouseEllipse元素的MouseMove事件上。
   
    另外一个要介绍的方法是FindName,其函数声明如下:    

retval = object.FindName(name)

    
    其name即是在XAML中元素的名称,它返回该元素的引用(有点像我们经常使用的getElementById).

    通过该方法我们就可以该XMAL中的元素了。
   
    目前我们只是完成了相应的代码声明工作。仅下面就是创建该silverlight对象的代码(因为要演示三种鼠标应用
场景,所以这里采用了参数化的方式来简化代码, 文件 CreateSilverlight.js):

 

//Instance:实例名称
//
Source:资源文件名称
//
ParentElement:相应的父元素名称
//
PluginID: 插件名称
function createSilverlight(Instance, Source, ParentElement, PluginID)
{
 
var scene = Instance;
 
 Silverlight.createObjectEx({
  source: Source,
  parentElement: ParentElement,
  id: PluginID,
  properties: {
   width:
'300',               
            height:
'300',              
            version:
'2.0',             
            isWindowless:
'true',
            background:
'aliceblue',
            framerate:
'24'
            version:
'2.0'     
  },
  events: {
      
//注意此处的代码使用方式,它将相应的prototype实例和相应方法
      //绑定到onLoad事件上
   onLoad: Silverlight.createDelegate(scene, scene.handleLoad),
   onError: 
function(sender, args) {
    
var errorDiv = document.getElementById("errorLocation");
    
if (errorDiv != null) {
     
var errorText = args.errorType + "" + args.errorMessage;
       
     
if (args.ErrorType == "ParserError") {
      errorText 
+= "<br>File: " + args.xamlFile;
      errorText 
+= ", line " + args.lineNumber;
      errorText 
+= " character " + args.charPosition;
     }
     
else if (args.ErrorType == "RuntimeError") {
      errorText 
+= "<br>line " + args.lineNumber;
      errorText 
+= " character " +  args.charPosition;
     }
     errorDiv.innerHTML 
= errorText;
    } 
   }
  },
  initParams:
null// 初始化参数
        context:null
 });
}

    到这里我们仅需要在HTM文件中写入下面的js代码,便可创建对象了: 

createSilverlight(new Silverlight_JsWeb.MoveScene(),
                  
"xaml/MoveScene.xaml",
                  document.getElementById(
"SilverlightControlHost_Move"),
                  
"MouseMove");

    其运行结果如下图所示:

             
     
    上面介绍和鼠标MOVE事件的处理方法。下面介绍一下鼠标元素拖动的方法:
   
    其JS声明如下(DragAdnDrop.js):   

//通过使用全局变量来记录鼠标的位置和是否停止拖动等信息
//
当前是否设置鼠标捕获
var isMouseCaptured;
//全局位置变量
var mouseVerticalPosition;
var mouseHorizontalPosition;

Silverlight_JsWeb.DragDrop 
= function() 
{
}

Silverlight_JsWeb.DragDrop.prototype 
=
{

 handleLoad: 
function(plugIn, userContext, rootElement) 
 {
     
this.plugIn = plugIn;
  
  
// 按钮事件挂钩示例: 查找按钮,然后附加事件处理程序
  var DragRec = rootElement.findName("DragRec"); 
  
  DragRec.addEventListener(
"MouseLeftButtonDown", Silverlight.createDelegate(thisthis.handleMouseLeftButtonDown));
  
  DragRec.addEventListener(
"MouseMove", Silverlight.createDelegate(thisthis.handleMouseMove));
  
  DragRec.addEventListener(
"MouseLeftButtonUp", Silverlight.createDelegate(thisthis.handleMouseLeftButtonUp));
 },
 
 
// 鼠标左键单击处理程序
 handleMouseLeftButtonDown: function(sender, mouseEventArgs)
    {
    
         
//获取当前鼠标左键按下的位置
         mouseVerticalPosition = mouseEventArgs.getPosition(null).y;
         mouseHorizontalPosition 
= mouseEventArgs.getPosition(null).x;
         isMouseCaptured 
= true;
         sender.CaptureMouse();  
    },
    
    
// 鼠标离开处理程序
    handleMouseMove: function(sender, mouseEventArgs)
    {
          
var item = sender;
          
if (isMouseCaptured) 
          {

            
// 计算当前对象的位置.
            var deltaV = mouseEventArgs.getPosition(null).y - mouseVerticalPosition;
            
var deltaH = mouseEventArgs.getPosition(null).x - mouseHorizontalPosition;
            
var newTop = deltaV + item["Canvas.Top"];
            
var newLeft = deltaH + item["Canvas.Left"];

            
// 对鼠标选中的元素设置新的移动位置.
            item["Canvas.Top"= newTop;
            item[
"Canvas.Left"= newLeft;

            
// 更新全局位置变量.
            mouseVerticalPosition = mouseEventArgs.getPosition(null).y;
            mouseHorizontalPosition 
= mouseEventArgs.getPosition(null).x;
          }
    },

   
    
//鼠标左键松开处理程序
    handleMouseLeftButtonUp: function(sender, mouseEventArgs)
    {
          isMouseCaptured 
= false;
          
          sender.ReleaseMouseCapture();
          
          mouseVerticalPosition 
= -1;
          
          mouseHorizontalPosition 
= -1;
    }

}

    上面代码中有两个方法要说明一下:        

retval = object.CaptureMouse()    

    该方法的调用者object即是支持被拖动的元素,当元素对象支持拖动时,该方法调用返回true   
  
    与上面方法相对应的是 object.ReleaseMouseCapture(), 它会放弃对当前元素的鼠标捕获操作。
   
    其最终的运行结果如下:

           
    
       
     前两个DEMO是对鼠标基本事件的操作。下面将会演示一下UIElement的Bubble问题。写过IE脚本的朋
友应该都会知道这个元素冒泡的问题这个问题有时我们希望发生的,有时即是我们不希望看到了。在XMAL
中,先声明元素在整个Canvas的最下面,而后声明的元素在最上面。这样当我们将鼠标从上面的元素移入
到下面的元素时,就会出现下图中所显示的结果(注意在两个元素交叉区域时下方所显示的元素名称):

          


    因为rect2是在rect1之后声明的,所以在交叉区域显示的是rect2。当然我们可以通过在相应元素中
设置Canvas.ZIndex 属性来改变这里顺序,如下所示:
  

<Rectangle
    
x:Name="Rect1"
    Width
="100" Height="100"
    Fill
="PowderBlue" Canvas.ZIndex="3"/>

  
<Rectangle
    
x:Name="Rect2"
    Canvas.Top
="50" Canvas.Left="50"
    Width
="100" Height="100"
    Fill
="Gold" Opacity="0.5" Canvas.ZIndex="2" />

  
<Polygon x:Name="Polygon1"
    Points
="50,200 150,125 200,275 300,200"  Stroke="Purple" StrokeThickness="2" Canvas.ZIndex="1">
    
<Polygon.Fill>
      
<SolidColorBrush Color="Blue" Opacity="0.4" />
    
</Polygon.Fill>
  
</Polygon>

  
     这样我们就可以控件鼠标事件的响应顺序了,如下图。

                  
 
     好了,今天的内容就到这里了。
 
     源码下载,请点击这里:)

   

 

posted @ 2008-07-08 12:30  代震军  阅读(3291)  评论(13编辑  收藏  举报