Hello World
Spiga

WPF/E CTP Quick Start - 第十部分:脚本和鼠标事件(翻译)

2006-12-18 15:56 by 老赵, 3235 visits

WPF/E支持使用JavaScript进行编程,能够使您为WPF/E内容增加交互性。

这篇文档包含了如下部分:

 

脚本与事件

WPF/E能够让您在事件触发时执行JavaScript代码,例如一个对象被加载之后,或者鼠标进入了一个对象。这样的脚本被称之为“Event Handler”。

为了定义一个“Event Handler”,您需要执行以下两步:

  • 在一个XAML文件里,添加下面的属性,使对象能够触发您的函数。

    someEvent="javaScript:myFunction"

    其中someEvent是您希望响应的事件名,而myFunction是您希望处理该事件的函数。

  • 在您的JavaScript文件中定义该函数。(关于建立一个JavaScript文件,请参照《WPF/E CTP Quick Start - 第一部分:创建一个WPF/E项目》。)

让我们来尝试写一个示例。在WPF/E中,所有的Canvas和形状元素都有一个事件叫做MouseLefButtonDown,它会在用户鼠标在元素之上,并且左键被按下时被触发。让我们来为这个事件写一个Event Hander,调用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="javascript:helloworld">
   
    <TextBlock Text="click me"  FontSize="50"/>
</Canvas>
function helloworld() {
    alert("hello world");
}

重新开始查看内容

您在声明一个Event Handler时不需要指定参数,但是如果您确实需要的话,您可以使用第一个参数“sender”作为触发事件的元素,而第二个参数“args”是一个包含了事件信息的对象。

 

设置属性

您可以使用JavaScript来设置WPF/E对象的属性。当一个属性为一个字符串或一个数字时,您可以简单地使用JavaScirpt设置它。如果属性为一个WPF/E对象,但是它有个类型转换器,例如一个SolidColorBrush,您可以用字符串形式来设置它。否则,您必须使用createFromXaml方法来实例化一个新的属性值。

下面的例子响应了CanvasMouseLeftButtonDown事件。在这个Event Handler中,通过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="javascript:changecolor">
   
    <TextBlock Text="click me"  FontSize="50"/>
</Canvas>
function changecolor(sender, args) {
    sender.background = "red";

    alert("Height is " + sender.Height);
}

重新开始查看内容

 

设置附加属性

如果要使用JavaScript设置一个附加属性,例如Canvas.Top,您可以使用下面的语法:

  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="javascript: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="javascript:e1Move"
        MouseEnter="javascript:e1Enter"
        MouseLeave="javascript:e1Leave"
        MouseLeftButtonDown="javascript:e1Down"
        MouseLeftButtonUp="javascript:e1Up"
        Height="100" Width="100"
        Canvas.Left="80" Canvas.Top="30"
        Stroke="Black" Fill="LightBlue"
        StrokeThickness="10" />
</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";
}

重新开始查看内容

另一个非常有用的事件是Loaded事件。通常您会在根元素里声明响应该事件,但是Loaded事件可以在任何UIElement上响应。Loaded事件提供了一个非常好的机会,可以让您在WPF/E控件显示的最后进行一些最后的改变。下面的例子响应了Loaded事件,将EllipseFill属性从Blue改成Red

<Canvas
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Ellipse Loaded="javascript: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来修改发起事件的对象,但是如果您需要调用的方法或者修改的属性是属于其它对象的呢?WPF/E元素提供了一个方法叫做findName,可以使您获得子元素。在使用findName获得对象之前,您必须使用x:Name属性在申明XAML时为对象提供一个名字。

下面的示例在鼠标点击Canvas时修改了EllipseFill属性。当Canvas发起事件时,changeEllipseColor函数被调用,sender是Canvas对象。该函数调用了sender.findName()函数获得了myEllipse对象,并且将它的Fill属性设为了红色。

<Canvas
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Background="Transparent"
    MouseLeftButtonDown="javascript: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";
}

重新开始查看内容

当您编写的脚本代码并不是被WPF/E元素的事件触发时(例如一个普通的HTML事件),您就无法得到一个sender参数,用来使用findName以获得一个WPF/E对象了。在这个情况下,您可以使用document.getElementById()来获得WPF/E的ActiveX控件,然后可以使用ActiveX控件的findName方法。

<Canvas
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Background="Transparent"
    MouseLeftButtonDown="javascript: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(sender, args) {
    var ag6 = document.getElementById("ag6");
    ag6.findName("myEllipse").fill = "red";
}

重新开始查看内容

在之前的例子里,ag6是您在HTML页面中创建WPF/E的ActiveX控件时,传入new agHost()ID,例如在文档中“第一部分:创建一个WPF/E项目”描述的那样:

<script language="javascript">
    // 创建一个WPF/E的ActiveX控件,这里的
    // 方法使您的WPF/E的内容在这个ActiveX控件
    // 被点击之前就创建完毕。
    new agHost(
       // 用于插入WPF/E ActiveX控件的元素,一般会使用
        // DIV元素,如果您在上一步改变了HTML元素的ID,
        // 您在这里也必须相应的改变。
        "agControl1Host",
       // WPF/E ActiveX控件的ID
       "ag6", 
       // 控件宽度
        "300px", 
       // 控件高度
        "300px", 
       // 控件的背景色
        "#D6D6D6", 
       // 源元素(存放XAML内容的Script标签)
        null, 
       // 存放WPF/E内容的XAML文件的URI
        "myxaml.xaml", 
       // 是否是无窗的
        "false", 
       // 最大帧率(Frame Rate)
        "30",
       // 处理错误的Handler,
        // 您能够将其设为一个方法的引用。
        null
    );
</script>

您可以在创建了ActiveX控件之后使用下面的代码,这使您能在以后不必再次获得ActiveX控件了。

// 方便起见,为WPF/E的ActiveX控件创建一个全局变量
// 它能让我们调用findName方法。
var ag6 = document.getElementById("ag6");

 

动态创建WPF/E对象

您可以使用createFromXaml方法使用JavaScript来创建一个新的WPF/E对象。下面的示例在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="javascript:createEllipse">
    
    <TextBlock Text="click for circle"  FontSize="40"/>
</Canvas>
function createEllipse(sender, args) {
    var agControl = document.getElementById("ag7");
    var e = agControl.createFromXaml(
        '<Ellipse Height="200" Width="200" Fill="Blue"/>');
    var canvas = sender;
    canvas.children.Add(e);
}

重新开始查看内容

请注意,JavaScript需要您将字符串放在同一行中,除非您用+连接多个字符串。还要注意的是在这里XAML单引号和双引号的使用:使用单引号来表示JavaScript字符串,在XAML字符串中使用双引号。

 

交互地控制动画

您可以使用Event Handler来控制动画。将您希望控制的Storyboard给定一个名字,这样您就可以使用它的begin、stop、pause和resume方法来交互式地控制动画。

<Storyboard x:Name="animation"
    Storyboard.TargetName="e1"
    Storyboard.TargetProperty="(Canvas.Left)"
    BeginTime="1">
    <DoubleAnimation RepeatBehavior="Forever" To="300"/>
</Storyboard>
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();
}

重新开始查看内容

 

下面该做什么呢?

在下一部分“示例控件”中,您会看到几个例子,展示了如何使用WPF/E来创建交互式的控件。

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

22 条回复

  1. 老赵
    admin
    链接

    老赵 2006-12-18 15:57:00

    难以想象WPF/E如何能够离开JavaScript。

  2. *悟*道*[未注册用户]
    *.*.*.*
    链接

    *悟*道*[未注册用户] 2006-12-18 16:59:00

    好象很不错。。。

  3. 老赵
    admin
    链接

    老赵 2006-12-18 17:29:00

    @*悟*道*
    不过我觉得WPF/E还是离不开JS,呵呵……

  4. 初学者[匿名][未注册用户]
    *.*.*.*
    链接

    初学者[匿名][未注册用户] 2006-12-18 17:42:00

    还不错...又学到新知识了

  5. 老赵
    admin
    链接

    老赵 2006-12-18 17:52:00

    @初学者[匿名]
    :)

  6. neuhawk
    *.*.*.*
    链接

    neuhawk 2006-12-18 19:23:00

    如果wpf/e 有wpf的控件,我会马上用,可是要我自己写控件,太难了.

  7. 老赵
    admin
    链接

    老赵 2006-12-18 21:25:00

    @neuhawk
    我想如果有那么多控件,客户端的Runtime会有多大呢?

  8. @book[未注册用户]
    *.*.*.*
    链接

    @book[未注册用户] 2006-12-18 21:30:00

    难道wpf不可以设计winform程序?或者设计winform程序时还要用到javascript?

  9. 老赵
    admin
    链接

    老赵 2006-12-18 22:19:00

    @@book
    Winform的话只有win能够运行了,而且需要有个庞大的基础,比如.NET Framework。

  10. kiven[匿名]
    *.*.*.*
    链接

    kiven[匿名] 2006-12-20 10:03:00

    我想知道,它如何与数据连接,如何操作数据!

  11. rr[未注册用户]
    *.*.*.*
    链接

    rr[未注册用户] 2006-12-20 13:14:00

    vs2005装了SP1
    再装WPE/E的那个 WPFE VS Template 就不让装了咋办
    猜想可能是没有正确识别VS版本

  12. 老赵
    admin
    链接

    老赵 2006-12-20 13:26:00

    @rr
    遇到什么错误呢?

  13. 老赵
    admin
    链接

    老赵 2006-12-20 13:26:00

    @kiven[匿名]
    借助AJAX的功能吧,我还是认为AJAX和WPF/E是相辅相成的。

  14. rr[未注册用户]
    *.*.*.*
    链接

    rr[未注册用户] 2006-12-20 18:56:00

    @Jeffrey Zhao
    截了个图
    http://www.ourplace.cn/WPFE.GIF

  15. 老赵
    admin
    链接

    老赵 2006-12-20 20:30:00

    @rr
    它的提示是您没有安装Visual Studio 2005的Web Project Extension,不知道您装了吗?

  16. rr[未注册用户]
    *.*.*.*
    链接

    rr[未注册用户] 2006-12-20 21:37:00

    Microsoft Visual Studio 2005
    版本 8.0.50727.762 (SP.050727-7600)
    Microsoft .NET Framework
    版本 2.0.50727

    已安装的版本: Enterprise

    Microsoft Visual C# 2005 55603-113-3000004-41923
    Microsoft Visual C# 2005

    Microsoft Visual Studio Tools for Office 55603-113-3000004-41923
    Microsoft Visual Studio Tools for the Microsoft Office System

    Microsoft Visual Web Developer 2005 55603-113-3000004-41923
    Microsoft Visual Web Developer 2005

    Microsoft Web Application Projects 2005 55603-113-3000004-41923
    Microsoft Web Application Projects 2005
    版本 8.0.50727.762

    Visual Studio 2005 Team Edition for Architects 55603-113-3000004-41923
    Microsoft Visual Studio 2005 Team Edition for Software Architects

    Visual Studio 2005 Team Edition for Developers 55603-113-3000004-41923
    Microsoft Visual Studio 2005 Team Edition for Software Developers

    Visual Studio 2005 Team Edition for Testers 55603-113-3000004-41923
    Microsoft Visual Studio 2005 Team Edition for Software Testers

    Crystal Reports AAC6G-K0CSA4K-U70001R
    Crystal Reports for Visual Studio 2005


    Microsoft Visual Studio 2005 Team Suite - 简体中文 Service Pack 1 (KB926604)
    此 Service Pack 是用于 Microsoft Visual Studio 2005 Team Suite - 简体中文 的。
    如果以后安装较新的 Service Pack,则会自动卸载此 Service Pack。
    有关更多信息,请访问 http://support.microsoft.com/kb/926604@Jeffrey Zhao

  17. 老赵
    admin
    链接

    老赵 2006-12-21 00:01:00

    @rr
    sorry,我不知道怎么回事了……

  18. 星宿.NET
    *.*.*.*
    链接

    星宿.NET 2007-01-09 10:53:00

    老赵,使用js脚本动态创建WPF/E那里你的展示窗体有错误.
    http://downloads.cnblogs.com/thcjp/JeffreyZhao/WpfeQuickStart/samples/scripting-create.js
    里的var agControl = document.getElementById("ag7");
    似乎错了,你用的是"agControl1"
    :)

  19. 老赵
    admin
    链接

    老赵 2007-01-09 15:23:00

    @星宿.NET
    运行有问题吗?这地方我的确改过,因为感觉似乎是Sample的错误。

  20. 星宿.NET
    *.*.*.*
    链接

    星宿.NET 2007-01-09 16:46:00

    @Jeffrey Zhao
    是有啊,你点一下click for circle
    ag7和你用的agControl1名称不对应啊,所以找不到对象,改统一即可吧
    PS:我在Sample里试了一下,没有错啊

  21. 老赵
    admin
    链接

    老赵 2007-01-09 19:26:00

    @星宿.NET
    的确错了,谢谢提醒,我方便的时候就改一下。:)

  22. Andy[未注册用户]
    *.*.*.*
    链接

    Andy[未注册用户] 2007-04-06 18:23:00

    我是初学哦,你讲有些我不懂啊!

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我