WPF VS Apollo
在Vista时代,身为编程员,就一定要具备Vista桌面应用开发的能力。而开发Vista桌面应用,最重要的就是要会WPF。本系列文章整理WPF技术的精华,以连载的方式,介绍如何使用WPF编写微软Windows平台。
什么是WPF?
WPF是Windows Presentation Foundation的缩写。WPF是一套API,利用WPF所开发出来程序可以是:
一般独立执行的Windows应用,也称为client应用。
或者是分布式(distributed)应用的前端——现在有一个更时髦的名称Rich Internet Application(RIA)。
虽然WPF是编写Windows平台的应用,但WPF应用绝对不同于以往的Windows应用:外在,WPF应用具有崭新的外观和新的图形效果(包含动画和3D);内在,WPF应用具有新的控件设计哲学和新的API。
WPF应用只能在.NET Framework 3.0的环境中执行,计算机上必须安装:
Windows Vista(自带.NET Framework 3.0)或者
Windows XP/SP2或者
加装.NET Framework 3.0的Windows 2003。
如果你是编程员,你的环境除了具备上述的要求之外,还必须配备:
Visual Studio 2005 Professional Edition(商业软件)
.NET Framework 3.0 and Windows SDK(免费)
Visual Studio Extensions for WCF, WPF(免费)
上列的免费软件都可以从微软的MSDN网站下载,除此之外,Visual C#已推出 Express
Edition,也可以免费下载。你可能想要使用免费的Visual C# Express Edition取代Professional
Edition,但是Visual Studio Extensions for WCF, WPF只能搭配Professional
Edition的Visual Studio 2005。由于Visual Studio 2005(以及Visual C# 2005
Express Edition)内附的.NET Framework SDK是2.0版,所以必须额外安装.NET Framework
3.0,并搭配Visual Studio Extensions for WCF, WPF。估计微软将在2007年底推出新版的Visual
Studio,届时只要直接安装Visual Studio就行了,不用像现在这么辛苦,拼拼凑凑地四处下载和安装软件。
如果你无法取得Visual Studio 2005 Professional Edition,也不想安装巨大的Windows
SDK(这东西大得吓人,需要1.15GB),那么直接利用免费的VisualC# Express Edition和免费的.NET
Framework 3.0即可,一样可以写WPF程序,只是会有两个缺点:
在Visual C#中没有WPF的template,你必须手动写每一行程序,且手动加入相关DLL的参考。(本文稍后介绍如何加入DLL参考。)
不能使用XAML。
Windows开发技术的历史
Windows已经有22年的历史,这22年来,微软官方主力推行的编程语言与API有四个分水岭:
1985~1991年:C搭配Windows API。目前我们已很少用C和Windows API写程序了,但还是有必要熟悉这样的技术,因为有些特殊的时候会用到。
1992~2001年:C++搭配MFC链接库(这段时间也是Visual Basic最风光的时候)。在历史上MFC是最多人用的Windows编程方法。我很高兴MFC这么糟糕的技术终于淡出历史了!
2002~2006
年:C#搭配Windows
Form。这段期间IT技术的焦点是在Web上,所以虽然大家都在用.NET,但真正的主角是ASP.NET,而不是Windows
Forms。Windows Forms还没等熬出头,WPF就出现了。Windows
Forms注定会是历史中“最少人使用的微软开发技术”。Windows Forms其实是不错的技术,但好技术(Windows
Forms)的下场是没人用,差技术(MFC)的下场是大家都在用。我只能说,Windows Forms生不逢时。
2007~今:C#搭配
WPF。你可能觉得很奇怪,微软为何释出两个作用相似,却不同且不相容的.NET API。其实,Windows
Forms在设计上比较偏向于传统的应用(类似Java Swing),没有考虑到Web/Markup的需求,所以后来微软才会设计全新的WPF。
Windows Form VS WPF VS Apollo
由于Windows Forms已经发展多年,所以控件(control)和标准对话框(dialog box)都比WPF更好,但是未来WPF却很有发展潜力。特别是:
如果你需要做很多客制化控件和绘图,WPF会比Windows Forms更适合。WPF和Windows
Forms在开发时,虽然都可以进行“视觉”和“逻辑”的切割,但是Windows Forms的视觉部分是使用Partial
Class,但WPF的视觉部分却是XML(XAML)。XML格式适合不懂编程的美工人员进行处理,微软也会在今年(2007)推出相关的设计工具
(Expression)。
WPF意图利用简化版本WPF/E走进各种装置,包括浏览器和手机。目前Windows Forms虽然可以用在Windows Mobile 5上,但是不能用在浏览器内。而WPF/E可以用在Windows Mobile 6上和各种浏览器内。
Adobe Apollo和WPF是类似的技术。如果你要开发跨平台的应用,当然选择Adobe Apollo(另一个选择是Java
Swing,但是在F3语言正式释出之前,我不认为Java是一个好选择),如果你要开发Windows平台专属的应用,当然要选择WPF,因为:
开发应用时,偶而需要呼叫OS的DLL,但Apollo 1.0不允许我们这么做(基于安全的理由)。
如果你确定你的应用不需要跨平台,那么采用操作系统所支持的开发方式,往往可以带来其它的边际效益。例如:用WPF开发Vista应用,可以让应用轻易地兼容于Power Shell;用Cocoa开发MacOS X应用,可以让应用轻易地兼容于AppleScript。
C# VS XAML
一般的WPF应用,都会同时包含:
程序代码(本系列文章使用C#):主要是处理逻辑的部分。
XAML(一种XML语言):主要是处理视觉的部分。XAML的英文发音为zammel。
结
合XAML和C#程序代码各自的优点,可以帮助我们建立更大型、更复杂的应用。你可以参考我上一期(2007年2月)的Apollo文章,C#其实就类似
ActionScript,而XAML则类似于MXML。任何WPF程序都可以只用C#,不用XAML就开发出来。而只有少部分简单的程序可以只用
XAML,完全不使用C#就开发出来。从这个角度来看,C#程序代码才是重点,而XAML只是让我们编程更方便。XAML所叙述的一切,编译时会被转成程
序代码。因此,如果你真的想要好好掌握WPF的技术,那么在学习阶段,应该将心思先放在程序代码的部分。每个WPF编程员都应该要对于WPF的程序代码部
分建立稳固的根基。
XAML的档案一般是用交互式工具(例如Expression)和编程工具(例如Visual Studio)所产生出来的,我们自然也应该善用这样的工具,毕竟XML本来就是给机器读的。但尽管如此,每个编程员还是有必要具备亲自动手编写XAML的能力。
WPF名称空间
开发WPF应用时,请特别注意下面的名称空间(namespace):
System.Windows:
这个名称空间包含了所有基本的WPF类别、结构(struct)、界面(interface)、delegate、以及列举(enum),其中包含了
Application与Window类别。WPF的开发应用,一般来说,一开始需要建立Application对象与Window对象。
System.Windows:它的WPF名称空间开头都是System.Windows,例如System.Windows.Controls、System.Windows.Input、System.Windows.Media。
System.Windows.Forms:虽然此名称空间是在System.Windows之下,但是它不属于WPF,而是最基本的Windows Forms名称空间。
其它的Windows Forms名称空间相当分散,包括System.Windows.Forms、System.Drawing、System.ComponentModel。
System.Windows.Forms.Integration:这个名称空间的类别是用来帮助Windows Forms和WPF程序代码之间做整合之用的。
一个简单的WPF应用
Application和Window可以说是最基本的WPF类别,两者皆属于System.Windows名称空间。顾名思义,Application用来代表整个应用,而Window用来代表一个窗口。
在一个应用中,只能建立一个Application对象,对于应用的其它地方来说,此Application对象的作用就如同固定船的锚一般。你在屏幕上是看不见Application对象的,但是可以看得见Window对象。
Window
对象出现在屏幕上,就是正常的Windows操作系统的窗口,具有标题列。标题列的系统选单icon是在左边,而最小化、最大化、和关闭窗口的icon是
在右边。此窗口具有一个可以调整窗口大小的边框,窗口中间很大的面积被一个client area(客户区)所占据。
基本上,建立最简单的WPF应用就是:
1. 建立窗口
2. 显示窗口
3. 让窗口进入讯息循环(message loop)(透过Application的协助)
其实传统的C/Windows API、C++/MFC、C#/Windows Form也都是这样的步骤。根据上面的三个步骤,编写出下面的WPF程序代码。这个程序代码相当简单,没用到继承:
using System;
using System.Windows;
namespace WPFTest
{
class Hello
{
// 程序进入点
[STAThread]
public static void Main()
{
// 1. 建立窗口
Window win = new Window();
// 设定窗口标题
win.Title = "Hello";
// 2. 显示窗口
win.Show();
// 建立Application对象
Application app = new Application();
// 3. 让窗口进入讯息循环
app.Run();
}
}
}
Main()是程序进入点,至于Main()放在哪个类别中,则无所谓。Main的前面都必须具有[STAThread] attribute,否则编译会失败。[STAThread]是用来指定,初始应用执行绪的执行绪模型是single-threaded apartment。STA是前朝COM时代的技术余孽,不太需要搞懂它,[STAThread]大致上的意思是:我们的应用不会使用源自于“执行期环 境”的多执行绪。
在Hello程序中,Main建立一个Window类别的对象,这个类别用来建立标准应用窗口。Title property是会显示在窗口标题列的文字,而Show方法会将窗口显示在屏幕上。
这
里最重要的步骤是:呼叫Application对象的Run方法。在传统Windows编程的思维中,这么做的目的是要建立一个讯息循环,让应用可以接收
使用者键盘或鼠标的输入。如果此程序是在Tablet
PC上执行,此应用也会接收到来自触控笔(stylus)的输入。Run方法一旦被呼叫,就不会返回,直到窗口被关闭为止。然后,Main方法结束,随后
Windows操作系统会做一些清除的工作。
Run()有另外一个版本,接收一个Window对象当参数。Run()会检查Window是否已经显示出来,如果尚未显示,Run()会呼叫Window对象的Show()。然后才进入讯息循环,所以这两行程序:
win.Show();
app.Run();
可以简化如下:
app.Run(win);
使用Visual C#
如果你使用Visual Studio 2005 Professional Edition且你有安装WPF extension,那么你可以采取下面的步骤来建立此Hello程序:
1. 从“File”选单,选取“New Project”。在“New Project”对话框中,选取Visual C#、Windows Presentation Foundation和Empty Project,并将项目命名为Hello,然后按下“OK”。
2.
在右边的“Solution
Explorer”中,“References”区域必须包含PresentationCore、PresentationFramework、
System、以及WindowsBase。如果在此“References”区域中,没有出现这些DLL,请手动将它们加上去,只要用鼠标右键点选
“References”,然后选取“Add Reference”就可以了(或者,从“Project”选单中,选取“Add
Reference”)。在这个“Add Reference”对话框中,点选“.NET” tab,然后选取必要的DLL,最后按下“OK”。
3.
在“Solution Explorer”中,用鼠标右键点选Hello的项目名称,然后从“Add”选单中选取“New
Item”(或者,从“Project”选单中,选取“Add New Item”)。在“Add New Item”对话盒中,选取“Code
File”,键入文件名称“Hello.cs”,最后按下“OK”。
4. 将前面的程序代码,键入Hello.cs档案中。
5. 从“Debug”选单,选取“Start Without Debugging”(或者,直接按下Ctrl+F5),就可以编译并执行此程序。
如果你使用Visual C# 2005 Express Edition,步骤和上面差不多,但要特别注意步骤2。你一定要手动将下面的DLL加入:
PresentationCore.dll(版本3.0.x.x)
PresentationFramework.dll(版本3.0.x.x)
System.dll(版本2.0.x.x)
WindowsBase.dll(版本3.0.x.x)
这
些DLL位于GAC(C:WINDOWSassembly)的深层目录中。由于你无法将GAC的DLL加入Visual
C#的项目(这是因为shfusion的遮蔽效果,造成Visual
C#无法看见GAC内的档案结构),所以你必须先透过“DOS窗口”(命令提示字符窗口),利用dir、cd、copy等指令,将这些档案找出来(这需要
花一点时间),复制到某个目录中(例如C:Assembly),然后再利用下面的方式将它们加入项目中当参考(references):
1. 在右边的“Solution Explorer”中,用鼠标右键点选“References”,然后选取“Add Reference”;
2. 翻到“Browse”页,找到PresentationCore……等档案的目录,选取这几个档案,然后按下OK。
今后如果需要用到其它.NET 3.0的API,也都可以用上述的方式将它们的DLL加入参考。
关闭与开启Console窗口
在Hello的例子中,你会发现执行时同时会出现一个console窗口,这是因为编译旗标设定的关系,你可以在项目的property中,调整此旗标。做法如下:
1.用鼠标点选右边的项目名称,并从选单中选取“Properties”(另一个作法是,从“Project”选单中选取“Properties”)。
2. 现在你可以检查看看项目的各种设定,也可以改变设定。特别注意,“Output Type”被设定为“Console Application”,显然这样的设定,并不会阻碍console程序更进一步地建立GUI窗口。
3. 将“Output Type”设定为“Windows Application”,这个程序将会和以前一样可以顺利执行,而这次不会再出现console窗口了。
在开发阶段,console窗口有时候是我们的好朋友,因为:
我们可以利用它来显示一些文字信息,以便debug。
如果程序的bug太多,甚至一开始就出问题,而无法将GUI窗口显示出来,或者进入无穷循环,这个时候,只要在console窗口中键入Ctrl+C,就可以轻易地将程序终结。