Window Presentation Foundation系列 (1)---从HelloWorld认知WPF
2011-06-21 17:22 libiver 阅读(504) 评论(0) 编辑 收藏 举报声明:欢迎任何人和组织转载本blog中文章,但必须标记文章原始链接和作者信息。
本文链接:http://www.cnblogs.com/leezhm/archive/2011/06/21/2086239.html
开拓进取的小乌龟------->cnBlogs 点滴点点滴滴 的Blog
Ok,作为一个Programmer,绝大部分人对一种全新的语言的第一个程序应该都是Hello,World吧。在这里我也从这个开始,一个最简单的Hello World。代码如下:
1: using System;
2: using System.Windows;
3:
4: namespace HelloWorld
5: {
6: class HelloWorld
7: {
8: [STAThread]
9: public static void Main(string [] args)
10: {
11: //Console.WriteLine("Hello, World! This is a most simple WPF Application");
12: }
13: }
14: }
使用命令行编译,如下 csc /out:.\HelloWorld.exe HelloWorld.cs。编译成功运行,运行会显示Hello, World! This is a simple WPF Application的一个消息。但是这个WPF很不完整,没有使用任何的WPF服务,也可以说跟WPF扯不上关系,它只是一个简单的C# Console程序。到底真正的WPF包含哪些关键的组件(或者核心的DLL文件)以及WPF能够做些什么?我们可以通过下面的图片来理解.
图 1
上图中标为暗红色的是WPF的三大核心组件,其中milcore组件,它的职责是完成与Direct3D的交互。并且出于效率和安全考虑,milcore由非托管代码实现。WPF 中的所有显示是通过 DirectX 引擎完成的,可实现高效的硬件和软件呈现。WPF 还要求对内存和线程执行进行精确控制。milcore 中的组合引擎受性能影响关系大,需要放弃 CLR 的许多优点来提高性能。WPF的另外两大核心组件PresentationFramework和PresentationCore都位于通用语言运行库(CLR)之上。而那么就可以看出,WPF的大部分代码都是以托管形式存在的。这两大组件提供了WPF项目需要的函数库和功能库,由于是以托管的形式存在,所以也避免了我们直接操作底层和出现诸如内存泄露的可能性。
图 2
从上面的这幅图可以看出一共分成了五大块(Core Presentation、User Interface Services、Base Services、Document Servies和XPS Viewer):
- Core Presentation:包含了所有的图形效果,如图形、2D图形、3D图形、文本、音频、视频和显示效果。同时还包括强大的动画效果,动画可以应用前面的所有元素。最下面的那个就是视觉基本元素。
- User Interface Services:包含了应用程序服务、部署服务、控件库、布局和数据绑定.
- Base Services:提供了XAML支持、提高开发效率、输入和事件的支持、属性系统。
- Document Servies和XPS Viewer则提供了基本的打印和表报服务,可以通过这些组件实现自定义的打印和显示效果。
好了,再继续改进Hello World,改进后的代码如下:
1: using System;
2: using System.Windows;
3: namespace HelloWorld
4: {
5: [STAThread]
6: public static void Main(string [] args)
7: {
8: //MessageBox.Show("Hello, World! This is a simple WPF Application");
9:
10: Window wnd = new Window();
11: wnd.Width = 800;
12: wnd.Height = 600;
13: wnd.Title = "Hello World";
14: wnd.Show();
15:
16: Application app = new Application();
17: app.Run();
18: }
19: }
再次通过命令行编译,编译命令如下(这里为了便于理解,我对编译命令做了排版,实际使用中并不需要这样)
1: csc /target:winexe /out:.\HelloWorld.exe
2:
3: /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\presentationframework.dll"
4:
5: /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\windowsbase.dll"
6:
7: /reference:"C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\presentationcore.dll"
8:
9: HelloWorld.cs
注意,在这里引用了prensentationframework.dll、presentationcore.dll和windowsbase.dll这三个WPF的核心DLL。在这里使用.net Reflector(http://reflectoraddins.codeplex.com/)来查看编译后的exe文件的IL代码如下:
图 3
由上图,我们可以清楚地看出来,WPF程序的编译过程,并且可以看到它链接了那些WPF组件。
当然,一个真正的WPF程序远不止一个消息对话框或者一个简单的什么都没有的窗体而已,它是需要有Application类的实例。在这里我们来分别继承一个Application和Windows,具体代码如下:
1: using System;
2: using System.Windows;
3: namespace HelloWorld
4: {
5: class HelloWorld : Application
6: {
7: [STAThread]
8: public static void Main(string [] args)
9: {
10: /* #region // simple I
11: MessageBox.Show("Hello, World! This is a simple WPF Application");
12: #endregion // simple I
13:
14: #region // simple II
15: Window wnd = new Window();
16: wnd.Width = 800;
17: wnd.Height = 600;
18: wnd.Title = "Hello World";
19: wnd.Show();
20:
21: Application app = new Application();
22: app.Run();
23: #endregion // simple II
24: */
25: #region // simple III
26: HelloWorldWnd wnd = new HelloWorldWnd();
27: wnd.Show();
28:
29: HelloWorld helloWorld = new HelloWorld();
30: helloWorld.Run();
31: #endregion // simple III
32: }
33: }
34:
35: class HelloWorldWnd : Window
36: {
37: public HelloWorldWnd()
38: {
39: this.Width = 400;
40: this.Height = 300;
41: this.Title = "Hello World Windows";
42: }
43: }
44: }
同样使用Reflector来查看IL代码,如下所示:
图 5
上两图分别是从Application继承的类HelloWorld和从Window继承的HelloWorldWnd类的IL代码,比较图3,基本上是一样的过程,只不过分别是俩个类而已。
不过通过最后的HelloWorld和HelloWorldWnd类,我们可以看出来,其实可以将WPF的代码分隔开来,HelloWorld里面实现了WPF的“行为”;而HelloWorldWnd则实现了WPF的“外观”。这样我们就可以分别将注意力放在不同的事情上,比如设计师可以专注于UI设计,而软件工程师则可以专注于程序的逻辑处理。好了,如果我们为WPF的“外观”的代码定义一种声明式的格式,并且这种格式的文件可以通过工具拖拽等方式来创建,那就Perfect了。是不是描述的有点像flex啊,好了其实我们是幸运的,MS为我们实现了这些。具体的在WPF中表现为XAML格式。用XAML来实现HelloWorldWnd类的代码如下:
1: <!-- HelloWorldWindow.axml -->
2: <Window x:Class = "HelloWorld.HelloWorldWnd"
3: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5: Title="Hello World Windows"
6: Width="400" Height="300">
7: </Window>
其实很简单的,一种声明式的语法,简单地描述了这个windows的特征。XAML的规范定义了一些规则,来把.Net的命名空间、类型、属性、事件等一系列元素映射成XAML的命名空间、元素和特征。XAML被尽可能地设计成直接映射,比如一个XAML元素就映射一个.Net的类名,一个XAML属性(Attribute)就映射成相应类的属性(Property)名或者类的相应的事件名。这样XAML不仅仅只能为WPF类所用,还可以让有默认构造函数的.Net的类可以在XAML文件中直接完成初始化。比如上面的Window类
好了,我们看看Visual Studio .Net 2010创建的一个WPF Application项目的结构图,截图如下:
图 6
从图6中标准WPF程序结构图可以看出,WPF需要PresentationCore、PresentationFramework和WIndowsBase这三个核心的组件的支持;XAML和Code-behind文件的关系;关键字partial在WPF中的作用。
代码隐藏(code-behind)文件的扩展名为.xaml.cs,它包含了xaml中未定义的部分,通过关键字partial让编译器把它和xaml定义合成一个完整的类定义。一般在代码隐藏文件中实现类的一“行为”处理,比如元素是事件等。
通过上面的例子,大概了解清楚了WPF程序的基本框架,当然一些具体的细节,需要自己具体去查询MSDN等资料。