正如WPF/E项目经理Joe Stegman说的那样,WPF/E是WPF Everywhere.那么究竟WPF/E是什么呢?它又是如何工作的呢?让我们现在就看看它.
这有几个WPF/E的页面效果演示,如果无法正常显示,请下载并安装WPF/E客户端运行库(1.1M)
演示地址:
Page Turner
Sprawl Game
Film Strip Slide-Show
Media Library
Simple Video Playback
概要:
- WPF/E开发背景及开发目标
- WPF/E的实质和前景
- WPF/E的实现原理及工作机制基础
- WPF/E参考资源
1.WPF/E开发背景及开发目标
随着.NET框架3.0的正式发布,Windows Presentation Foundation(WPF)即Windows表现层基础,Windows Communication Foundation(WCF)即Windows通信层基础和Windows Workflow Foundation(WWF)即Windows工作流基础,三大基础成为开发组织方式新的实现,为开发分工协作提供了更好的模型和支持,并大幅度的完善了微软.NET类库.WPF作为表现层基础开发库,提供了对DirectX更好的支持,优化了2D和3D表现层引擎,与WinForm开发紧密结合,实现了传统的Win32和WinForm对XAML(拓展应用程序标记语言)程序的支持和装载功能.然而WPF却未能实现ASP.NET WebForm装载XAML程序,而且在非3.0运行库支持平台上WPF无法正常工作.
出于WPF的局限性,WPF/E应需而生,WPF/E对Web应用开发ASP.NET 2.0作出拓展,实现
- 更轻松,更自由的网络应用程序开发
- 提高网络应用程序对媒体文件的表现效果和支持性
- 应用最新的标准
- 采用友好的AJAX和XAML表现
当然.WPF/E并非仅仅定义在网络应用上,它的跨平台性,可拓展性及优越的兼容性势必使WPF/E在实际应用上得到更多层面的拓展.
2.WPF/E的前景和实质
WPF/E是对图形界面,动画效果,媒体文件及XAML程序支持性的拓展,相信大家对WPF的展示效果也有所了解,在VISTA下,WPF将界面效果展示得淋漓尽致,玻璃,半透明,圆角,多边不规则图形,倒影等等.当然WPF的展示效果还不仅于此,WPF的动画效果也令人叹为观止,倒映,水波纹,滚动,浮动等等.试想下,如果我们将这些效果应用在网页上,那么动画页面便不再仅仅是FLASH的天地了.
说了这么多.WPF/E到底是什么呢?
WPF/E实际是通过JavaScript在普通的HTML页面上,将一个XAML程序以对象的方式呈现.
而仅仅是呈现么?
当然不是,在呈现之后.NET Framework会讲传统的HTML DOM树与XAML程序生成的XAML DOM树结合.这样我们可通过JavaScript同时将两个DOM树联系起来,形成HTML,ASP.NET和XAML的交互.这样整个Web应用程序形成了一个可以相互通信的有机体系.
同时,WPF/E仅仅是小型的客户端运行库,所以它可以轻松实现跨平台安装,并且对媒体文件的支持非常好,其内建的WMV,WMA,MP3解码器摆脱了以往需要安装Windows Media Player才可以播放Windows媒体文件的烦恼.
WPF/E将于明年被集成到ASP.NET,.NET FxCL及CLR Managed Code中.
3.WPF/E的实现原理及工作机制基础
首先来看一下下面这幅简单的WPF/E页面结构图
如上图,在一个普通的HTML文档中,WPF/E通过object或embed对象元素,以ActiveX控件的形式,将XAML程序的一个实例插入页面中,参数以object或embed的param属性传入XAML程序.然后WPF/E建立XAML DOM树,通过HTML DOM树和XAML DOM树,我们可以轻松的取得页面中任何对象的ID属性,并可以随意在JavaScript中引用其对象.
现在我们来模拟一下上面的过程.
1.建立XAML元素并指定ID
2 <Canvas xmlns=http://schemas.microsoft.com/winfx/2006/xaml/presentation
4 xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml >
5 <Rectangle x:Name="myRect" Fill="Orange" Width="100" Height="100" Canvas.Top="10" Canvas.Left="10"/>
6 </Canvas>
7</script>
2.在HTML页面中插入一个DIV做为XAML程序的容器
2</div>
3.在页面中插入一个object/embed元素.用来承载ActiveX控件.并由该ActiveX控件负责调用XAML程序
2 classid="CLSID:32C73088-76AE-40F7-AC40-81F62CB2C1DA">
3 <param name="SourceElement" value="agControlXaml" />
4 <param name="BackgroundColor" value="White" />
5</object>
这样就可以生成一个简单的WPF/E页面了.完整代码如下:
IE6+
2<head>
3</head>
4<body>
5<script type="text/xaml" id="agControlXaml">
6 <Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
7 xmlns:x=http://schemas.microsoft.com/winfx/2006/xaml >
8 <Rectangle x:Name="myRect" Fill="Orange" Width="100" Height="100" Canvas.Top="10" Canvas.Left="10"/>
9 </Canvas>
10</script>
12<div>
13 <object id="AgCtrl1" height="312px" width="354px"
codebase="xcpctrl.cab#version=0,0,3,0"
classid="CLSID:32C73088-76AE-40F7-AC40-81F62CB2C1DA">
14 <param name="SourceElement" value="agControlXaml" />
15 <param name="BackgroundColor" value="White" />
16 </object>
17</div>
18</body>
19</html>
FF
2<head>
3</head>
4<body>
5 <script type="text/xaml" id="agControlXaml">
6 <Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
7 <Rectangle x:Name="myRect" Fill="Orange" Width="100" Height="100" Canvas.Top="10" Canvas.Left="10"/>
8 </Canvas>
9 </script>
10 <div>
11 <embed id="AgCtrl1" height="312px" width="354px" SourceElement="agControlXaml" BackgroundColor="White" type="application/xcp-plugin"/>
12 </div>
13</body>
14</html>
效果:
随着CTP的发布,通常该加载过程会被封装在一个JavaScript方法中, 当页面被加载时,浏览器通过object的classid属性或embed的pluginspage来找到特定类型的ActiveX控件,创建控件实例,并指定该ActiveX控件的ID,由该ActiveX控件寻找param中name为SourceElement的script XAML元素,或param中name为Source的XAML程序地址参数,ActiveX控件在容器元素中创建XAML程序的一个实例.
具体如下:
调用方法:
2 //(用来放置WPF/E ActiveX控件的HTML元素常用<div>)
3 "wpfobj", // 我们创建的WPF/E ActiveX控件的ID
4 "900", // 宽度
5 "710", // 高度
6 "#ffB42600", // 背景色
7 null, // SourceElement (Scrpt标记名,包含XAML)
8 "mainPage.xaml", // Source XAML源文件地址
9 "false", // 是否无窗口
10 "24", // 最大祯率
11 null); // OnError事件 (方法名--无括号)
封装的源代码(aghost.js):
2 function agHost(hostElementID, id, width, height, backgroundcolor, sourceelement, source, windowlessmode, framerate, errorhandler) {
3 var hostElement = document.getElementById(hostElementID);
4 var innerHTML;
5//assign error handler
6 if(errorhandler == null) {
7 errorhandler = "aghost_errorhandler";
8 }
9
10//IE detection
11 if((navigator.appVersion.indexOf('MSIE') != -1)) {
12 try {
13 var WPFE = new ActiveXObject("AgControl.AgControl.0.8");
14 innerHTML = '<object id="'+id+'" width="'+width+'" height="'+height+'" classid="CLSID:32C73088-76AE-40F7-AC40-81F62CB2C1DA">';
15 if (sourceelement != null) {
16 innerHTML += ' <param name="SourceElement" value="'+sourceelement+'" />';
17 }
18 if (source != null) {
19 innerHTML += ' <param name="Source" value="'+source+'" />';
20 }
21 if (framerate != null) {
22 innerHTML += ' <param name="MaxFrameRate" value="'+framerate+'" />';
23 }
24 if (errorhandler != null) {
25 innerHTML += ' <param name="OnError" value="'+errorhandler+'" />';
26 }
27 if (backgroundcolor != null) {
28 innerHTML += ' <param name="BackgroundColor" value="'+backgroundcolor+'" />';
29 }
30 if (windowlessmode != null) {
31 innerHTML += ' <param name="WindowlessMode" value="'+windowlessmode+'" />';
32 }
33 innerHTML += '<\/object>';
34 }
35 catch(e) {
36 innerHTML = '<div width="'+width+'" height="'+height+'" >';
37 innerHTML += 'You must install "WPF/E" (codename) December 2006 CTP to view this page: ';
38 innerHTML += '<A href="http://go.microsoft.com/fwlink/?LinkID=77792&clcid=0x409">Get "WPF/E!"</A>';
39 innerHTML += '</div>'
40 }
41 }
42
43 //FF/Windows detection
44 else if((window.GeckoActiveXObject &&