Silverlight——微软的RIA解决方案[DSJ5]
AJAX技术的不足之处
从这个世纪开始,人们展开双手全面拥抱因特网,甚至依赖因特网而生活,相当多的应用程序都开始朝向Web化发展,为了解决Web上令人诟病的使用者操作接口问题,各大技术阵营纷纷推出了AJAX解决方案,来处理Web环境中,使用者操作接口上的问题。
但是这样显然还不够,从另一个角度来看,即使有了AJAX技术的加持,整个Web应用程序的客户端依旧被框在HTML这个框框当中,现今有太多的Web应用程序需要跳出浏览器上的HTML框架,网页上需要影音动画、需要实时图表、需要能够以2D或是3D方式呈现的动态绘图技术,但是这些都不是标准的HTML或AJAX所能提供的。
不仅如此,这些功能必须能够与现有的Server端技术加以整合,让Web应用程序可以动态抓取Server端数据库中的信息,再透过前端浏览器上的展示技术以优质的画面效果呈现在客户端的浏览器上,如此一来,才能真正达成我们实际的需要。
这类需求俯拾皆是,从电子地图、在线看屋看车、实时影音、股市交易实时图表……太多的Web应用需要多媒体技术的加入,否则以ASP.NET开发出来的网页一点都没有互动感,只能静静的躺在浏览器上让使用者点选。
微软终于在2007年,因应RIA需求而推出全新的解决方案,即是所谓的“Silverlight”。
Silverlight技术架构
当微软在构思整个Silverlight技术时,研发团队似乎认真的参考了Flex的特性,吸取了其中的优点,同时也弥补了齐中的不足之处。和Flex的任务相同,Silverlight必须能够在客户端呈现出炫丽的页面效果,同时间又必须顾及Web应用程序的Thin-Client特性,必须免安装、跨平台、适合各种浏览器,并且能够轻易的和服务器端的ASP.NET(或其它Server端开发技术)沟通。
下图为Silverlight 1.0环境下的开发架构:
|
图片:Silverlight-0177.tif |
|
|
从上图当中您可以发现,所谓的Silverlight技术,是在浏览器上Plug In了一个Silverlight Player,这个Player可以从Server端下载.xaml与.xaml.js这两个档案并加以执行。
扩展名为.xaml档案以微软自订的xaml语法来描绘要显示在Silverlight Player当中的图形、文字、以及动画,而.xaml.js则是用来在浏览器上控制以xaml语法所描绘出的每一个Silverlight元素。
例如,下面这个以Silverlight开发出来的RIA:

其中画面上的每一个图形、影像都是透过.xaml档案来描述的,而当鼠标点选『搜寻』按钮,或是某一张照片,相应的会触发一个『事件』(请注意这个事件是执行在浏览器端的JavaScript事件),该事件就是透过.xaml.js档案来处理。
如果需要进一步的抓取后端数据库内容,则可以在JavaScript程序代码当中透过AJAX技术来完成。
与现有ASP.NET(PHP、JSP)技术的整合
对于Silverlight来说,并不一定绝对需要和ASP.NET技术加以整合,即使单纯的.html页面也可以将Silverlight应用程序执行的非常好,只是这样的Silverlight程序仅跑在浏览器端(使用者端),若不透过AJAX技术,并无法存取到后端(服务器端)的数据库内容。
但是对ASP.NET来说,却可以藉由Silverlight技术来大幅的提升其缺乏的互动性能,以弥补在客户端浏览器上呈现信息时,仅透过HTML标记而无法满足使用者的窘境。您可以使用ASP.NET Futures Release当中的XAML控件,让ASP.NET开发人员可以直接在页面当中整合Silverlight技术。
不只如此,由于Silverlight是透过纯前端(浏览器端)的JavaScript程序代码来运作,因此在技术上当然也可以和ASP、PHP、JSP、或其它服务器开发技术加以整合。
更重要的是,在Silverlight当中,每一个XAML元素都有着丰富的事件,开发人员可以透过捕捉这些事件,并撰写适当的事件处理程序代码与使用者互动。
例如,底下这个范例,当使用者点选Silverlight图表上任何一个长条图时,动态的出现该长条图所代表的数值或相关信息,甚至把使用者点选长条图的动作传递(回报、告知)给后端的ASP.NET程序:
|
图片:0003.tif |
|
|
在传统的Web应用程序当中,想在页面上动态绘制出图表,并且点选图表上的某个局部元素(例如上例中的某一个Bar),再将被点选的Bar以及相关信息回报给Server端的ASP.NET程序,这部份在过去的Web应用程序当中,是必须大费周章才能完成的功能。如今Web开发人员透过Silverlight将会轻松不少。
在Silverlight当中目前所支持的重要事件包含:
|
事件 |
内容 |
|
MouseMove |
当鼠标在该元素上移动时被触发。 |
|
MouseEnter |
当鼠标进入该元素范围时被触发。 |
|
MouseLeave |
当鼠标离开该元素范围时被触发。 |
|
MouseLeftButtonDown |
当鼠标左键按下该元素时被触发 |
|
MouseLeftButtonUp |
当鼠标左键放开该元素时被触发 |
|
KeyDown |
键盘上的按钮被按下时触发 |
|
KeyUp |
键盘上的按钮被放开时触发 |
至于如何在Silverlight当中存取Server端的数据库中的信息呢?
在Silverlight 1.0当中,我们可以透过JavaScript以AJAX等技术来完成。如此一来,在客户端独立执行的Silverlight程序,也可以和Server端妥善的配合,在页面上呈现出更有意义的信息。
解剖Silverlight应用程序架构
前面我们曾经提过,截至Silverlight 1.0的版本,我们要开发Silverlight应用程序,关键的两个主角依旧是.xaml和.xaml.js档案,前者是用以描述画面上图形以及动画的XAML指令码;后者则是我们熟悉的JavaScript,可用来控制Silverlight当中的XAML元素。
Silverlight对于场景的主要观念是以画布(Canvas)和对象(Element)的方式来架构。
请参考下列程序代码,这是一个最简单的Silverlight程序代码片段(仅XAML部分,目前并未包含JavaScript):

呈现出的结果如下:
|
图片:0001-p.tif |
|
|
类似ASP.NET的Code Behind观念,在Silverlight 1.0的开发架构当中,Silverlight应用程序可分为.xaml和.xaml.js两个档案,并透过<embed>指令嵌入.html(或.ASPX、PHP、JSP)页面当中,例如底下的.html檔:

请注意其中第11行,这几行指令让开发人员可以在.html页面当中嵌入一个.xaml档案,并且让浏览器启动Silverlight Plug-In组件,同时执行该.xaml档。
回头看我们的.xaml档案,在这个.xaml档案中,我们利用XAML宣告式语法来描述要呈现在客户端浏览器Silverlight Player当中的向量对象。
目前页面上只有一张具有灰蓝底色的画布,以及一个红色的矩形。接着,我们要继续看.xaml如何与JavaScript档案配合。
前面我们曾经提过,.xaml档案之所以能够和使用者互动,关键在于javaScript档案的配合,请看底下的这个范例:

上面这段.html页面和刚才介绍的『EX01.xaml』完全相同,唯一不一样的地方,是加入了一段引用JavaScript档案的指令:
|
<script type="text/javascript" src="EX02.xaml.js"></script> |
除了本来叫用的.xaml档案,您会发现我们又在.html页面当中叫用了.xaml.js档案,用来与.xaml档案配合。
我们开启该.xaml.js档案来看看,有一个JavaScript的function:

先看过就好,这个JavaScript不会自动执行,当然是需要与.xaml档案配合。因此,请再打开EX02.xaml档案:

有没有发现『Rectangle』指令和刚才也有点不同,加上了一个『MouseLeftButtonDown』的Attribute(属性)。
『MouseLeftButtonDown』表示当使用者按下了该『Rectangle』,浏览器会尝试执行『MouseLeftButtonDown="OnRectangleClick"』当中所指定的JavaScript函式:
|
EX:SilverlightStudyHostCom\_Exam\Fundamentals\EX02\EX02.xaml.js |
|
function OnRectangleClick(sender,e) { alert('矩形被按下了,原始长度为:'+sender.Width); sender.Width-=30; } |
因此,上面的JavaScript函式就会被启动执行。
其中的参数意义为:
|
参数 |
意义 |
备注 |
|
Sender |
触发该事件的对象 |
在这个例子当中是Rectangle |
|
e |
触发该事件时的相关可用参数 |
例如,在这个例子当中,可用e.GetPosition(sender).x取得使用者点选时的鼠标x坐标 |
读者请勿担心,后面我们会有一整个章节在讨论这个部份。
执行结果如下:
|
图片:Silverlight-0002.tif |
|
|
由于『EX02.xaml.js』当中有这样的指令:
|
alert('矩形被按下了,原始长度为:'+sender.Width); |
因此画面上会显示出上图中出现的这段文字,其中sender表示被按下的对象『Rectangle』,而sender.Width则是Rectangle物件的长度。
接着『EX02.xaml.js』当中又有一行指令:
|
sender.Width-=30; |
因此画面上的矩形会缩短30px,每点选一次,就缩短一点(30px),直到在画面上消失为止。
重要的Silverlight开发观念
从上面的这两个例子当中,读者必须意会几个重要的Silverlight开发观念:
1. 开发Silverlight应用程序的关键在于.xaml和.xaml.js这两个档案,.xaml档案以XML格式的指令码,在画面上绘制出向量元素,.xaml.js档案则透过JavaScript来控制.xaml档案中的向量元素。
2. 扩展名为.xaml的档案必须被嵌入网页(.html或是.aspx或其它型式网页均可)中,才可以透过Silverlight Plug-In来执行 (嵌入网页的方式目前您看到我们是透过<embed>指令,但是其实后面我们会介绍更简单更优秀的方法) 。
3. 扩展名为.xaml的档案用来描绘将来要呈现在Silverlight Plug-In当中的图形内容(这些Silverlight元素未来我们统称为『Silverlight Content』或是『Silverlight Element』)。
4. 每一个Silverlight Element都有一些『事件』可以被触发,当『事件』被触发时,可以指定相对应的JavaScript function来负责处理。同时我们也可以透过JavaScript来控制Silverlight Element的属性(例如上例中的『sender.Width-=30;』)。
5. 请特别注意.xaml和.xaml.js两者之间的档名并不一定要有必然的关连,例如上面范例的文件名可以改为default.html配上EX02.Xaml再加上default.js(JavaScript档案并不一定非要是和.xaml档案同名再加上.js,只是我们习惯这样写以方便管理)。
6. 上例中,EX02.xaml.js之所以被加载执行,是因为default.html页面上有一段『<Script Src=…>』指令,而非文件名长的跟EX02.Xaml很像就会被自动执行。
7. 上例中,点选Rectangle对象时,之所以会执行到EX02.Xaml.js中的『function OnRectangleClick()』函式,关键在于.xaml档案当中Rectangle对象指令码中的『MouseLeftButtonDown』属性(Attribute)。
所以整个执行的动作如下:

不仅可以透过JavaScript来动态的控制Silverlight Plug-In当中的XAML对象(例如上例中使用者点选Rectangle时,我们将其缩短),更进一步的,未来我们可以在JavaScript的事件当中,透过AJAX技术,达成存取服务器端数据并动态的显示在Silverlight当中的能力。
只要我能动态Render JavaScript
刚才我们提到了可以透过JavaScript来控制Silverlight的属性或事件。不仅如此,我们也可以透过JavaScript的createFromXaml动态建立Silverlight元素,还可以透过JavaScript来动态调整Silverlight当中每一个Xaml元素的属性,甚至外挂上一个事件……但是这些都是透过JavaScript,如果要能从ASP.NET当中来控制呢?
整个关键在一句话:只要我们能够以异步的方式从后端ASP.NET程序代码当中,动态Render出JavaScript丢给浏览器执行,就能够在不换页的状况底下,以ASP.NET程序来控制Silverlight。
那如何从ASP.NET以异步的方式来产生所需要的JavaScript呢?关键在ScriptManager类别的RegisterStartupScript方法:
|
ScriptManager.RegisterStartupScript (Me.Page, GetType(String), key值,要动态产生的JavaScript, True) |
RegisterStartupScript的用法与ClientScript类别当中的同名方法RegisterStartupScript完全一致,主要的目的是从后端ASP.NET程序代码当中,动态的将以字符串形式存在的JavaScript码,Render(产生)到前端浏览器当中。两者之间差异在ScriptManager.RegisterStartupScript支持以异步(不产生Postback)的方式来进行这个动作。
其中的『key值』是为了避免重复Render JavaScript到前端所作的区隔设计。而『要动态产生的JavaScript』则是以字符串形式存在的变量,最后一个参数『True』,是指是否要在Render时自动帮我们加上一段<Script>…</Script>标记。
我们来看使用的方式,请从工具相当中拖曳一个UpdatePanel,并在UpdatePanel当中拖曳一个Button:
|
图片:Silverlight-0132.tif |
|
|
接着设定Xaml控件的XamlUrl属性为Scene.Xaml,其内容如下:
|
EX:SilverlightStudyHostCom\_Exam\AJAX_Integration\EX01\Scene.xaml |
|
<Canvas xmlns="http://schemas.microsoft.com/client/2007" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="640" Height="480" Background="Yellow" Name="Page"> </Canvas> |
接着,我们在放置于UpdatePanel的Button1对象上Double-Click,撰写底下程序代码,其中第1行的Xaml变量当中的Rectangle指令,就是我们要动态显示在Silverlight Player当中的对象(的Xaml指令码):

接着我们在第6行把这段Xaml码组成JavaScript程序,放入变量JS中,第8,10行则分别是『把Xaml码建立成Xaml元素』的JavaScript程序代码,以及『把Xaml元素动态加入Silverlight Content』的JavaScript程序代码。
组好之后的JavaScript指令码(存放在JS字符串变量当中),内容应如下:
|
var xamlCode = "<Rectangle Width='207' Height='33' Fill='Red' Stroke='Black' Canvas.Left='124' Canvas.Top='72' />"; var XamlElement = document.getElementById('Xaml1').content.createFromXaml(xamlCode);" document.getElementById('Xaml1').content.root.children.add(XamlElement); |
我们再透过第12行RegisterStartupScript指令,将上面这段动态组出的JavaScript注册到页面上,由于这一段JavaScript一旦透过ScriptManager.RegisterStartupScript以异步的方式注册到页面上之后,就会被浏览器直接执行,因此页面上的Xaml控件中Silverlight Content,会立刻动态的加入这个Rectangle对象:

执行这个范例,使用者所看到的是,当按下ASP.NET的Button,就可以在画面上动态的出现一个长方形。很神奇,对吧!!!
整个技术的关键在于,由于按钮被放在UpdatePanel控件当中(安装了ASP.NET AJAX之后就会有UpdatePanel控件),当使用者按下Button之后,会透过AJAX技术来触发异步的Postback,因此页面不会换页,但是后端Button1_Click事件会被执行,然后在执行的过程当中,我们透过ASP.NET程序代码动态组出需要的JavaScript,再透过ScriptManager.RegisterStartupScript以异步的方式把动态组出的Javascript丢给前端浏览器执行,达到我们需要的『从后端ASP.NET程序代码当中来控制Silverlight』的执行效果。
透过这样的技术我们可以轻易的在ASP.NET当中设计出抓取后端数据库来呈现出的动态报表,可以让前后端非常漂亮的整合:
|
图片:Silverlight-0134.tif |
|
|
上图中这些数据都是从后端数据库当中动态抓取并且利用前面所介绍的非同部技术绘制在前端的Silverlight对象当中,这个技术相当实用。
以异步技术为基础
在前面介绍的这个技术当中,一切都是以异步的技术为基础,透过ASP.NET AJAX 1.0套件来完成,我们看整个技术的架构图:
|
图片:Silverlight-0135.tif |
|
|
|
整个执行的顺序如上图所示,当使用者在前端以鼠标点选放置于UpdatePanel中的Button时,浏览器端会产生一个『异步的HttpRequest』,因此,后端ASP.NET的Button_Click事件被触发,这时后可以透过后端的ASP.NET程序抓取数据库内容,或是在服务器端进行计算或数据交换(刚才我们的程序代码当中并没有做这一部分,这部份是暂时先略过的),完成后,组出适当的JavaScript程序代码,回传给浏览器端,浏览器接受后,会开始执行这段以异步方式产生的JavaScript,并且直接影响Silverlight Plug-In当中的Xaml内容。关于ASP.NET AJAX与异步技术的观念,可以参考笔者著作『ASP.NET AJAX应用剖析立即上手』。 |
为RIA铺路
透过这样的一个技术架构,我们就可以利用ASP.NET AJAX所提供的异步技术,让后端ASP.NET程序代码得以动态的更新前端的Silverlight内容,过程中并不需要Postback,在页面上足会有相当好的动态呈现效果。
如此一来,我们就可以让ASP.NET和Silverlight之间通力合作,让两者之间的整合变得相当容易,以这样的技术架构为开发RIA来铺路。
我们可以透过这样的架构以ASP.NET来直接控制Silverlight上的每一个元素,您会发现不管是Silverlight Element的动态产生、属性控制、动画或媒体播放,甚至Silverlight前端的事件处理机制,每一种JavaScript可以控制Silverlight的功能。在这样的技术架构下,我们也都可以透过ASP.NET来控制,这样的相互整合才有更深的意义。


[DSJ6] 










