技术开发 频道

手把手带你从WPF基础向企业应用进阶

     【IT168 技术文档】很多时候了解一项新技术的历史和趋势往往比这项技术的本身价值还要重要。WPF作为一项新技术(已经三年多了,或者应该叫老技术了),我们都有必要了解它的来龙去脉,尤其是公司的CTO、技术总监、架构师等决策层,因为他们对技术的选型及应用具有决定权。

  1.开篇前言

  对于开发者来说,了解自己正在从事的这个技术的前世今生,有助于我们更好的认识技术本身的价值,也可以避免我们少走一些弯路。从IT技术发展的这些年可以看出,技术对于各大公司只是竞争的一种手段,而对于大多数程序员来说技术就是特饭碗甚至于生命,所以大家站的立场不同,也会形成各自不同的观点。放眼现在的全球IT巨头,摩托罗拉和诺基亚等企业的逐渐衰落,苹果、谷歌和微软等巨头公司在硅谷已经上演了三国大战。国内腾讯、百度、新浪、网易、盛大、搜狐、阿里巴巴等公司在各个领域的混战已经表明新的市场和新的技术是他们的主要战场,那么有些老技术必将淡出历史舞台,部分新技术也将被推到台前,作为IT人了解这些可以帮助我们看得更远,避免一直处在自己的狭小空间当中,等到了某个技术的真正失落,我们才骤然发现失业已经降临到我们身边,前途将一片灰暗!

  2.WPF介绍

  Windows APIWindows Presentation Foundation (WPF) 是下一代显示系统,用于生成能带给用户震撼视觉体验的 Windows 客户端应用程序。使用 WPF,您可以创建广泛的独立应用程序以及浏览器承载的应用程序。 WPF 的核心是一个与分辨率无关并且基于向量的呈现引擎(这样就可以保证图像和影像具有高清晰度),旨在利用现代图形硬件的优势。WPF 通过一整套应用程序开发功能扩展了这个核心,这些功能包括可扩展应用程序标记语言 (XAML)、控件、数据绑定、布局、二维和三维图形、动画、样式、模板、文档、媒体、文本和版式。WPF 包含在如下图的 Microsoft .NET Framework 3.0中,使您能够生成融入了 .NET Framework 类库的其他元素的应用程序(因为WPF包含在.NET Framework 3.0 里面,所以我们这里不列出3.5和4.0的框架)。

1、开篇

1、开篇

  .NET框架以及元素依赖图

  3.WPF技术发展历史

  微软在1983年春季就宣布开始研究开发Windows,到现在已经有27年的历史,这27年来,微软官方主力推行的编程语言与API有四个主要阶段:

  · 1983~1991年:C搭配Windows API。当时的程序员是很少的,并且开发一个项目也比较的不容易。

  · 1992~2001年:这段时期C++搭配MFC库。在历史上MFC是最多人用的Windows编程方法。但此后MFC技术也逐渐退出了历史的舞台。

  · 2002~2006年:(C#、VB以及其他语言)+Windows Form框架。这段期间IT技术的焦点是在Web上,所以虽然大家都在用.NET,但真正的主角是ASP.NET,而不是Windows Forms。Windows Forms还没等熬出头,WPF就出现了。Windows Forms注定会是历史中“最少人使用的微软开发技术”。Windows Forms其实是不错的技术,在很多方面都做得挺不错,比如在UI上、图形编程上、开发效率上、稳定性上都做得很让人敬佩,但是我们最后看到的结果却是大家没有引起足够的重视,很多人更偏向于用Delphi和MFC,对Windows Forms却视而不见,所以造成的最后结果就是Windows Forms生不逢时。

  · 2007~现在 :2007年1月30日,Windows Vista正式全球同步发布。它之所以能实现那么绚丽的效果,最关键的一点就是Windows Presentation Foundation(WPF),WPF所带来的震撼视觉效果和用户体验使Vista的效果如此绚丽,虽然Vista在后来最终成为了一个败笔,但它为Windows 7打下了坚实的继承。后台语言(C#、VB以及其他语言)+XAML构成的WPF。你可能觉得很奇怪,微软为何释出两个作用相似,却不同且不相容的.NET API。因为时代的改进,用户对视觉感受需求不断提高。因为WPF支持硬件加速、精确颜色、浮点坐标、动画实现、三维、视频感受等要求提高。而传统的 Winform 是到不到这些效果的。

  4.之前的技术

  旧的事物迟早会退出历史舞台,新的生命会经过曲折的里程登上王座。从图像界面的出现那一刻起,用户界面(UI)就进入了一个特殊的历史时期。在随后几年里,出现了很多具有历史意义的界面风格。现在,经典的Windows窗口风格已经存在了10多年,即使是深受用户喜爱的Windows XP风格也已出现五年有余。无疑大家与我一样,期待着全新视觉界面的出现。另一方面,当今计算机处理芯片飞速发展,特别是显示芯片,显示卡几乎成为了一台微型的计算机。但是,其强大的处理能力却没有得到充分的应用。目前,显示卡GPU(Graphics Processing Unit)的处理能力大多只应用在游戏和多媒体领域。为了给用户提供最强的体验,满足不断提高的用户视觉需求,Windows Vista引入了全新的图形子系统——WPF。她能充分利用显示卡的处理能力提供给用户最绚的视觉效果。

  在Windows Vista出现之前,Windows平台的图形系统主要有:GDI、GDI+、Direct3D。其中,GDI的应用领域最为广泛。GDI图形系统已经形成了很多年并且已经逐渐形成了自己的一套开发体系。它提供2D图形处理、文本处理,以及有限的图像处理功能。虽然在一些显示卡上支持部分的GDI加速,但是其效果与现在的Direct3D相比还是很弱小。GDI+开始出现是在2001年,它引入了2D图形的反走样、浮点数坐标、渐变以及单个象素的Alpha支持。它几乎支持所有的常用图像格式。但是,GDI+没有任何加速功能(全部是用软件实现)。

 Wpf的发展历史

 

 Wpf的发展历史

  NT依赖简图

  为了兼容性,GDI和GDI+在Windows Vista和现在的Windows 7中仍被支持,只是功能稍有改变,但大体上都还是没有差别。

  5.WPF——王者的到来

  在Windows Vista和Windows 7中,GDI、GDI+和WPF并行存在。但是,WPF所有的操作都不依赖于GDI和GDI+,而是间接依赖于强大的Direct3D。请参考下面的WPF核心组件图。

 

 WPF的构设及基本机构

  WPF核心组件图

  上图中的标示为暗红色的是WPF的三大核心组件,其中milcore组件,它的职责是完成与Direct3D的交互。并且出于效率和安全考虑,milcore由非托管代码实现。WPF 中的所有显示是通过 DirectX 引擎完成的,可实现高效的硬件和软件呈现。WPF 还要求对内存和执行进行精确控制。milcore 中的组合引擎受性能影响关系大,需要放弃 CLR 的许多优点来提高性能。

  WPF的两大核心组件PresentationFramework和PresentationCore都位于通用语言运行库(CLR)之上。那么就可以看出,WPF的大部分代码都是以托管形式存在的。这两大组件提供了WPF项目需要的函数库和功能库,由于是以托管的形式存在,所以也避免了我们直接操作底层和出现诸如内存泄露的可能性。

  关于WPF的是怎样执行的,我这里也根据自己的一些理解画出了如下执行序列图。此图比较简单,但很容易说明问题,如果把中间的每一步骤都画出来,可能会比较大,为了使大家能看明白,所以中间省略了一些操作。

 WPF的构设及基本机构

WPF执行序列图

  前面说了WPF的前世今生,那么对于开发人员,我们最关心的WPF所提供的功能。下面的这幅图展示了WPF基本功能和服务。 

 WPF的构设及基本机构

  WPF基本功能结构

  正如上面的这幅图,可以看出一共分成了五大块(Core Presentation、User Interface Services、Base Services、Document Servies和XPS Viewer):

  · Core Presentation:包含了所有的图形效果,如图形、2D图形、3D图形、文本、音频、视频和显示效果。同时还包括强大的动画效果,动画可以应用前面的所有元素。最下面的那个就是视觉基本元素。

  · User Interface Services:包含了Application Services(应用程序服务)、Deployment Services(部署服务)、Controls(控件库)、Layout(布局)和Data Binding(数据绑定).

  · Base Services:提供了XAML支持、Accessibility(提高开发效率)、Input&Events(输入和事件的支持)、Property

  System(属性系统)。

  · Document Servies和XPS Viewer则提供了基本的打印和表报服务,可以通过这些组件实现自定义的打印和显示效果。

  基于上面的特性以及我们使用的情况可以总结出:

  在输入方面:WPF支持键盘、鼠标、手写笔、触摸屏,蓝牙录入、视频扑捉等,所以基本没有任何限制,在和外部设备的交互上:有驱动、COM、Win32或通信协议支持的任何设备。打印和报表方面:可访问打印对话框、打印队列、打印窗体、控件以及很多可选操作,同时对报表也支持得很好。同时支持流文档和固定文档,对命令的支持以及对文件的无限制访问,最后尤其在动画、图形图像、3D、影像的支持相当好(其他技术是很难做到的),所以WPF除了在性能方面存在着缺陷以外,其他方面可以说是做得非常优秀,同时我们有信心相信微软会在这方面做得更好!

  6.与现有技术的对比

  WPF作为一项已经用了将近三年的技术,它到底和现有的一些技术有哪些区别和联系呢?下面一副图简单的介绍了它和现在的一些技术的相似之处。

  从上面可以看出,WPF技术和其他的技术有很多相似之处,比如XAML和XHTML、Styles和CSS等尤其相似,所以对我们的开发人员来说学习也不是一件难事。

WPF

现在的技术

XAML

XHTML

Layout

WinForms 2.0 Panels

Data Binding

ASP.NET Syntax

Data Templates

ASP.NET Templates(Atlas)

Styles

CSS

Control Templates

 

3D

Managed DirectX

Animation

Flash

  7.关于前景

  关于WPF的前景,我不想做过多的介绍,有很多人已经对这方面做了很深入的研究,那么我们就可以做一下简单的总结:

  由于WPF带来了很多优秀的功能和特性:

  1.超强的用户体验;

  2.简单便捷的部署方式(易于更新升级);

  3.更简便的编程方式。

  4,实现绚丽效果比较简单。

  所以在以下几个方面得到了很广泛的应用:

  1.企业应用系统(主要做一些管理系统,国内已经很多公司在使用了);

  2.一些Silverlight目前很难达到的效果同时又要求能从网络浏览到(如Asahiyama Zoo (日本北海道旭山动物园))

  3.桌面应用程序(如雅虎推出即时通讯软件和QQ等)。

  4,一些对效果要强较高应用的产品

  WPF正因为有那么多优秀的特性和功能并且微软一直在这方面努力,我们相信它一定会带来一场C/S用户程序的革命。对这个应用,我也曾专门了解过,在国内现在很多公司都在对WinForm进行升级到WPF,在国外如美国和印度等国家,对WPF的使用也逐渐普遍起来。上周公司首席科学家请客到新加坡一家六星级酒店吃饭,我以项目组附带的形式很荣幸也被邀请,旁边刚好是一个印度的Architect,我也顺便问了他们国家对Windows azure、WPF和Silverlight等技术的应用,发现他们国家对这些技术应用得很早并且也形成了自己的一些成熟体系。最近公司做的项目有很多以色列人来演示他们做的智能系统(UI用WPF实现,智能扑捉用摄像头,这样人站在电视机前面就可以用自己的身体玩很多体验,比如你可以真实体验三维游戏、你可以用你的身体直接做很多网络里的事情),他们比我们现在做的系统(我们的系统是用WPF做UI,然后在电视上通过蓝牙和遥控器实现点播网络视频、游戏和新闻等)高级很多,同时也让我们看到他们对这方面的研发能力。所以相信WPF一定可以逐渐流行起来,就让我们拭目以待。

  8.参考资料

  提到参考资料,大家第一感觉就是MSDN,当然我也不例外,这个网站基本上是学习微软技术的首选站点,除了这个网站以外,我还参考了很多其他的社区和网站,基本上都在.NET 技术社区之我见(英文篇)做了介绍,比如CodeProject、CodePlex 、windowsclient、C# Corner等,除了这些网站还有一些国外技术专家blog。

  1. Programming Windows Presentation Foundation

  这本书出得很早,在学WPF之初就是这本书和MSDN作为教材,优点:书中讲解的语言浅显易懂并且讲解的顺序和思路也很清晰,内容也是面面俱到,例子也举得很恰当。缺点是讲得很简单,稍偏向于入门书籍;书中的理论和例子都是针对于WPF的测试版,所以和正式的版本有一些出入,你会发现从书中拷贝下来的例子在程序中不能运行,这个你也不要见怪,只要能明白原理就行。

  2. Windows Presentation Foundation Unleashed (WPF) (Unleashed)

  这本书是WPF正式版出来以后出版的,所以和上一本比起来就有很大的优势,并且讲的内容也比上一本详细,所以在很长一段时间,除了MSDN,它就成了很权威的教材。在阅读的时候虽然没有Programming Windows Presentation Foundation那么轻松,但同时这里面的例子会给你带来很强的成就感。

  这本书是Adam Nathan写的,Adam是WPF Team的核心成员,也是WPF的专家。

  3. Applications = Code + Markup: A Guide to the Microsoft Windows Presentation Foundation

  WPF官方网站(http://wpf.netfx3.com)上推荐的书。

  这本书是Charles Petzold写的,也是WPF的专家。所以里面有很多的技术内幕和使用技巧都值得我们学习和操练,但我一直没有坚持看完,原因很简单,这本书不太适合入门,所以当时就没有选择这一本书,到学会了WPF以后,又经常关顾于国外的各大社区和论坛,上面很多内容可以解除你对WPF学习和使用中的疑问,所以它就一直搁置到了一边,直到写这个系列之前才翻完大半。

  4,WPF4是大家都期待的,因为前面几个版本存在着一些问题,如性能优化不上去、某些特性不支持等原因。那么WPF4的公布,让很多人都比较欣喜,如下第一排3本就是针对WPF4(VS2010)的,所以有兴趣的同仁也可以去找相关的资源。

  

 Wpf的相关参考资料

  当然国内也有一些书籍可以参考,如微软经典红皮书对WPF的讲解可以作为入门学习,还有WPF揭秘,虽说有一些翻译上的小错误,但是整体还是可以的。

  9.效果展示

  上面谈了这么多WPF的东西,有些没有接触过WPF的同仁也许会问:WPF到底能实现什么样的效果?WPF在哪些公司用到过?WPF究竟能不能应用于企业开发,那么我这里就简单收集了一些WPF的一些效果图和一些商业运用产品截图,希望大家看到以后,能对WPF有一个全面的了解。

  WPF企业使用案例(部分案例介绍来自网络):

  AMD Live : AMD为提升PC用户数字娱乐体验的新平台,一个结构化、可视化的在线照片、音乐、视频的播放软件

  从这个界面来看真的是非常强大,娱乐性已经与苹果系统几乎无异。 

 实例效果展示

           Chosun Daily iReader :基于WPF技术做的朝鲜日报阅读器,可以看到高保真影像。

实例效果展示

  Entellium Rave:中小企业CRM提供商 Entellium

  专供中小企业使用的 CRM系统,漂亮的界面与复杂内容的结合,逻辑层与表现层的分离使得这种平衡得以实现。 

 实例效果展示

  WPF概念版QQ

   实例效果展示

 实例效果展示

  Asahiyama Zoo (日本北海道旭山动物园)。

  是微软和日本北海道旭山动物园共同制作的动物园虚拟体验工具,你可以通过它对动物园进行虚拟体验,实现了很好的效果。  

 实例效果展示

 

  

  10.WPF开发基础

  本系列文章默认情况下,开发环境为Windows XP+SP3英文版和Visual Studio 2008+SP1英文版。要使用Windows 7 Professional和Visual Studio 2010开发环境的时候会附加说明。在搭建好开发环境之后,打开VS2008,选择创建项目(Create Project),出现如下图所示的选择项目模板的对话框:

Wpf开发基础

  在项目模板选择对话框中选择WPF Application,修改项目名称(Name)(已经截图完毕,所以没能改名,望见谅),和存储位置(Location),点击 确定 (OK)按钮,便成功创建了一个WPF应用程序,模板中文件层次结构如下图所示(在References里面自动引入了图一中的PresentationCore、PresentationFramework、WindowsBase三大核心程序集):

 

 Wpf开发基础

  图二

 Wpf开发基础

  在App.xaml中,指定项目运行时启动的是窗体:Window1,还可以定义我们需要的系统资源以及引入程序集等,详细看下图介绍:

Wpf开发基础

  在Window1.xaml中设计窗体的外观,首先,我们将窗体的Title更改为:XAMLWithScript,然后设置窗体的其他属性和事件 。完成了这些设置以后,我们就可以对窗体添加内容了,本实例对窗体添加了一个Button,然后对Button进行了一些简单的设置,详细如下图所示:

 Wpf开发基础

  上图没有对一些概念讲全,所以下面这幅图用另外一个窗体对某些概念进行了补充,由于我把很多概念都画到了图里面,所以在此就不做过多解释,详细如下:

 Wpf开发基础

  11.Expression工具的使用

  由于自己主攻方向不在这个方面,所以对这些工具也只是会使用而已,会用Expression做一些基本的效果和应用,但更多时候都是在visual studio里面手写代码,不过有的时候为了配合美工进行代码集成,也会接触这些工具。

  在 Expression Design 中打开作品文件。(这个作品有可能是你用其他工具创建的,也可以是你用Expression Design 设计的,但个人认为它还是没有Photoshop/CorelDraw/Fireworks等工具好用。)

  如果要导出切片,请从“工具箱”中选择“切分”工具,围绕所要导出的作品区域绘制一个矩形,然后在“属性”面板中的“编辑切片”下,设置切片的属性(如“Name”)。

  单击“文件”菜单上的“导出”。此时,将显示“导出”对话框。

  在“要导出的项”下,选择以下选项之一:

  · “整个文档” 导出文档中的所有作品。

  · “选定对象” 只导出那些在美工板上选定的项目。

  · “切片” 只导出生成的切片。您可以根据情况选择更改所显示的每个切片的属性。

  接下来设置“格式”,请选择以下任一选项:

  · “XAML Silverlight 画布” 导出单个 XAML 文件,其中包含表示为画布版式面板中的对象的所有作品。您可以在 Expression Blend 3中将此 XAML 文件导入到 Microsoft Silverlight 项目内,以用作独立的文档(启动的 XAML 文件或以编程方式加载的 XAML 文件),或将对象复制并粘贴到另一个 XAML 文档中。

  · “XAML WPF 图形画笔” 导出一个资源字典,其中包含表示为图形画笔资源的所有作品。您可以在 Expression Blend 3 中将此 XAML 文件导入到 Windows Presentation Foundation (WPF) 项目内,然后将这些资源应用于项目中的对象的画笔属性。

  · “XAML WPF 画布” 导出单个 XAML 文件,其中包含表示为画布版式面板中的对象的所有作品。您可以在 Expression Blend 3 中将此 XAML 文件导入到 Windows Presentation Foundation 项目内,以用作独立的文档(启动的 XAML 文件或以编程方式加载的 XAML 文件),或将对象复制并粘贴到另一个 XAML 文档中。您还可以在 Expression Blend 3 的“设计”视图中打开该文件,右键单击任意一个或多个对象,然后通过选择“工具”菜单上的选项,利用这些对象来创建按钮或用户控件。

  在对话框底部的“位置”框旁边,键入导出文件所在的文件夹的路径(我们这里就保存在D盘)。还可以设置下列选项:

  如果决定导出“整个文档”或“选定对象”,还需要输入文件的名称。如果决定导出“切片”,则可以根据情况选择一个版式面板以包含所有对象。

  单击“全部导出”以导出文件。 Expression工具的使用

    在 Expression Blend 3 中打开的项目内,单击项目菜单上的添加现有项

    在添加现有项对话框中,浏览找到所导出的一个或多个 XAML 文件,选择这些文件,然后单击打开

Expression工具的使用

  6.WPF和WinForm案例

  · 介绍

  这个例子主要展示同一个需求用WinForm和WPF分别进行实现,通过这个例子,我们可以看到两者之间的区别和联系,同时也可以对我们的项目选型带来一定的参考作用(原型来自于Josh Smith的一篇文章,个人觉得讲得非常不错,所以对原有例子进行了改造,进而有了这个案例)。

  当然作为一项新技术,WPF带来了很多功能,但在使用这些功能的同时也会带来很多缺点,这是不可避免的,正所谓”有利必有弊“吧!所以我们这个例子并不是讲WPF有如何如何的好,怎样用WPF代替WinForm,而是从两者实现同一个需求进行简单的对比。

  这个例子是用Visual Studio 2008编写的,所以大家可以下载下来进行查看.

  · 特别声明

  这个程序并不是要展现声明优秀的架构也不是为了宣扬WPF的种种好处,所以没有采用当前比较热门的MVP、MVVM模式进行开发,同时项目当中你可以看到很随意的代码,没有对IOC、AOP以及设计模式进行应用,这也是考虑到具体需求和例子简单的原因,况且这里也没有必要,我们在做项目的时候也要时刻注意什么时候用什么开发框架、开发模式以及项目整体架构。

  · 程序概览

  这个例子非常简单,需求就是展示三大社区的基本信息,同时你可以在输入框对其进行修改,当焦点切换的时候,你就会看到它会自动进行修改,你把鼠标放在图片上面会提示社区的ID等等。我在这里没有用复杂的逻辑和高深的架构,只是想通过这个例子展示WinForm的WPF的差异和联系,所以在程序处理上可能会有很多漏洞,比如没有对输入进行验证,你可以输入空格和任意字符等。

  下面是WinForms版本的截图:

 WPF和WinForm案例

    下面是WPF版本的截图:

 WPF和WinForm案例

    如果你编辑了某个社区的中文名称或者英文名称,然后把焦点移到另外一个地方,这些更改就会通过右上角的全名体现出来,因为他们都是通过绑定到公用字段来实现这些操作的。

    整个项目结构如下图所示:

 WPF和WinForm案例

    整个项目一共就三个工程,第一个工程BusinessObjects WpfAppWinFormsApp公用的业务类库,WinFormsApp是用WinForm实现的版本,WpfApp是用WPF实现的版本。那么我们下面就简单分别进行一些介绍:

 

  公用代码部分(BusinessObjects)

  这两个应用程序都是使用的BusinessObjects作为逻辑类库,BusinessObjects中的Company对UI所使用的数据进行了Mock。所以他们在需求方面都是一样的,由于比较简单,所以请看下面代码:

Collapse
using System;
using System.ComponentModel;
using System.IO;
using System.Reflection;

namespace BusinessObjects
{
public class Company : INotifyPropertyChanged
{
    
#region Creation

    
public static Company[] GetCompanys()
    {
        
// In a real app this would probably call into a data access layer to get records from a database.
        
return new Company[]
        {
            
new Company(1, "博客园", "CNBlogs", GetPictureFile(1), new DateTime(2004, 1, 12)),
            
new Company(2, "51CTO", "51CTO", GetPictureFile(2), new DateTime(2005, 3, 1)),
            
new Company(3, "CSDN", "CSDN", GetPictureFile(3), new DateTime(2000, 1, 20)),
        };
    }

    
private static string GetPictureFile(int CompanyID)
    {
        
string fileName = String.Format("emp{0}.jpg", CompanyID);
        
string folder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        folder
= Path.Combine(folder, "Images");
        
return Path.Combine(folder, fileName);
    }

    
private Company(int id, string chineseName, string EnglishName, string pictureFile, DateTime startDate)
    {
        this.ID
= id;
        this.chineseName
= chineseName;
        this.EnglishName
= EnglishName;
        this.PictureFile
= pictureFile;
        this.StartDate
= startDate;
    }

    #endregion
// Creation

    
#region Properties

    
public int ID { get; private set; }

    
string _chineseName;
    
public string chineseName
    {
        
get { return _chineseName; }
        
set
        {
            
if (value == _chineseName)
                
return;

            _chineseName
= value;

            this.OnPropertyChanged(
"chineseName");
            this.OnPropertyChanged(
"FullName");
        }
    }

    
string _EnglishName;
    
public string EnglishName
    {
        
get { return _EnglishName; }
        
set
        {
            
if (value == _EnglishName)
                
return;

            _EnglishName
= value;

            this.OnPropertyChanged(
"EnglishName");
            this.OnPropertyChanged(
"FullName");
        }
    }

    
public string FullName
    {
        
get { return String.Format("{0}, {1}", this.EnglishName, this.chineseName); }
    }

    
public string PictureFile { get; private set; }
    
public DateTime StartDate { get; private set; }

    #endregion
// Properties

    
#region INotifyPropertyChanged Members

    
public event PropertyChangedEventHandler PropertyChanged;

    
protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler
= this.PropertyChanged;
        
if (handler != null)
            handler(this,
new PropertyChangedEventArgs(propertyName));
    }

    #endregion
}
}

 

  上面这段代码没有什么不寻常的地方,大家写WinForm和Asp.Net也会写这样的逻辑类,只是要注意Company 实现了INotifyPropertyChanged 接口,大家看到这个接口只有一个OnPropertyChanged的方法,这个方法就是我们要说的属性变更通知方法,就是说当一个属性改变了,我们需要做些什么来响应这些改变。

  WinForms实现介绍

  WinForms版本就包含一个Form 和一个展示社区信息的custom UserControl, 这个Form 包含了一个FlowLayoutPanel控件, 它主要的作用就是用来承载每个社区的实例. 那么代码就如下所示:

 

Collapse
public partial class Form1 : Form
{
    
public Form1()
     {
         InitializeComponent();

        
// Create and initialize a usercontrol for each Company.
         foreach(Company com
in Company.GetCompanys())
         {
             CompanyControl comCtrl
= new CompanyControl();
             comCtrl.Company
= com;
             this.flowLayoutPanel.Controls.Add(comCtrl);
         }
     }
}

  CompanyControl是我们创建的一个UserControl,由于每个CompanyControl都要显示一个Company对象的属性值,我在这里使用了BindingSource控件来进行绑定,这样做也是为了和WPF更接近考虑(增强对比性,呵呵)。具体如下截图:

11、WPF和WinForm案例(2)

  如上图所示,我们用了BindingSource来获取数据,但有一个属性除外,那就是Company ID,请看下面代码:

 

Collapse
namespace WinFormsApp
{
    
/// <summary>
    
/// A WinForms control that displays an Company object.
    
/// </summary>
    
public partial class CompanyControl : UserControl
    {
        
public CompanyControl()
        {
            InitializeComponent();

            
// Convert the picture file path to a Bitmap.
            Binding binding
= this.CompanyPicture.DataBindings[0];
            binding.Format
+= this.ConvertFilePathToBitmap;
        }

        void ConvertFilePathToBitmap(
object sender, ConvertEventArgs e)
        {
            e.Value
= Bitmap.FromFile(e.Value as string);
        }

        
public Company Company
        {
            
get { return this.CompanyBindingSource.DataSource as Company; }
            
set
            {
                this.CompanyBindingSource.DataSource
= value;

                
// The Company's picture shows a tooltip of their ID.
                if (value != null)
                {
                    
string msg = "Company ID:  " + value.ID;
                    this.toolTip.SetToolTip(this.CompanyPicture, msg);
                }
            }
        }
    }
}

  这里有几点需要注意.在绑定的时候,我们对PictureFile 字段进行了转换,这个是必须做的. 如果不那样做, 这个图片会绑定失败,因为在绑定的时候它不能自动把string类型直接转化为Image类型.

  现在我们已经把Company绑定到了我们的控件上, 这里我需要给PictureBox一个tooltip的效果. 这个tooltip将显示 Company ID, 前缀显示为 "Company ID:". 现在这个是在代码里面写的,没有在窗体中发现有WPF ToolTip等类似的工具,不知道大家用到过没有?

  总的来说, 这是一个很简单的例子,我们的大部分功能也是用代码没有写代码,是通过visual designer进行实现的.然后通过一部分代码把它衔接起来, 我们看到Windows Forms是一个非常快速和实用的开发平台.

  WPF实现介绍

  WPF版本我这里就做得很简单了,由于开发WPF程序提供了很多模板和工具,所以我这里基本没写什么代码,全部的代码都是通过XAML实现,并且大部分都是自动生成的,只是我们要根据项目具体情况做一些修改就行。

  这个WPF项目同样有一个Window 和一个custom UserControl, 和 WinForms 版本基本一样. 只是WinForms中用 FlowLayoutPanel来承载EmployeeControls 控件, 而WPF 用的是ItemsControl 来承载这个用户控件.更加可喜的是,WPF通过模板来进行定制,所以我们就不需要像WinForms那样写循环加载控件的代码,下面就是WPF用XAML实现的窗体代码: 

Collapse
<Window
  x:
Class="WpfApp.Window1"
  xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local
="clr-namespace:WpfApp"
  xmlns:model
="clr-namespace:BusinessObjects;assembly=BusinessObjects"
  Title
="WPF App" Height="558" Width="581"
  WindowStartupLocation
="CenterScreen"
  
>
  
<Window.DataContext>
    
<ObjectDataProvider
      ObjectType
="{x:Type model:Company}"
      MethodName
="GetCompanys"
      
/>
  
</Window.DataContext>
  
<Grid Width="555">
    
<Label
      Name
="label1"
      HorizontalContentAlignment
="Center" VerticalAlignment="Top"
      FontSize
="20" FontWeight="Bold"
      Height
="36.6" Margin="0,16,0,0"
      
>
       .NET 中文社区大比拼
</Label>
    
<ItemsControl
      ItemsSource
="{Binding}"
      HorizontalContentAlignment
="Center"
      Margin
="46,59,25,0"
      Focusable
="False"
      
>
      
<ItemsControl.ItemTemplate>
        
<DataTemplate>
          
<local:CompanyControl />
        
</DataTemplate>
      
</ItemsControl.ItemTemplate>
    
</ItemsControl>
  
</Grid>
</Window>

 

  在如下的XAML代码中,这里有几点需要注意,。Window的DataContext赋予了一个ObjectDataProvider的对象,而ObjectDataProvider又会调用GetEmployees这个方法。所以一旦把DataContext设置到Company 对象,并且把ItemsControl的ItemsSource设置为“{Binding}” 就意味着该控件里面会自动显示Company 对象的所有数据。

  这里我们并不需要像WinForm一样用循环的方式创建CompanyControl的实例。这是因为ItemsControl中的ItemTemplate属性设置为了一个DataTemplate,同时ItemsControl中的ItemsSource绑定到了Company 的对象数组,那么ItemTemplate就会知道如何创建一个CompanyControl,所以大家看到这里写的代码就相对变少了,这也是XAML的一个优点之一。

  该CompanyControl的后台CS文件也是空的(除了必须的InitializeComponent),所以它不像的WinForms应用程序那么累赘,界面和逻辑紧密的耦合在了一起。下面就是CompanyControl的XAML代码, 这个代码相对来说就比较简单了。

 

Collapse
<UserControl x:Class="WpfApp.CompanyControl"
    xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
    Height
="137" Width="481">
  
<Border
    BorderBrush
="Black"
    BorderThickness
="1"
    Margin
="2"
    SnapsToDevicePixels
="True" Width="469">
    
<Grid Height="129" Width="451">
      
<Image Source="{Binding PictureFile}"
           Margin
="10" Name="image1" Stretch="Fill"
             Width
="150" Height="80" HorizontalAlignment="Left" >
        
<Image.ToolTip>
          
<TextBlock>
            
<Run TextBlock.FontWeight="Bold">Company ID:</Run>
            
<TextBlock Margin="4,0,0,0" Text="{Binding ID}" />
          
</TextBlock>
        
</Image.ToolTip>
      
</Image>

      
<Label
        Content
="{Binding FullName}"
        Height
="34" Margin="99,2,0,0"
        Name
="中英文名称"
        VerticalAlignment
="Top"
        HorizontalContentAlignment
="Right"
        FontSize
="16" FontWeight="Bold" />

      
<Label Margin="190,34,0,0" Name="chineseNameLabel"
             FontWeight
="Bold" Height="28"
             VerticalAlignment
="Top"
             HorizontalAlignment
="Left"
             Width
="73">中文名称:</Label>
      
<TextBox
        Text
="{Binding chineseName}"
        HorizontalAlignment
="Right" Margin="0,39,10,0"
        Name
="textBox1" Width="172" Height="23"
        VerticalAlignment
="Top" TextDecorations="None" />

      
<Label FontWeight="Bold" Height="28" Margin="190,0,0,34"
             Name
="EnglishNameLabel" VerticalAlignment="Bottom"
             HorizontalAlignment
="Left"
             Width
="73">英文名称:</Label>
      
<TextBox
        Text
="{Binding EnglishName}"
        Height
="23" Margin="0,0,10,34" Name="textBox2"
        VerticalAlignment
="Bottom" HorizontalAlignment="Right"
        Width
="172" />

      
<Label Height="28" Margin="190,0,185,2"
             Name
="startDateLabel" VerticalAlignment="Bottom"
             FontWeight
="Bold">创建日期:</Label>
      
<Label
        Content
="{Binding StartDate}"
        Height
="28" HorizontalAlignment="Right" Margin="0,0,10,2"
        Name
="startDateValueLabel" VerticalAlignment="Bottom"
        Width
="172" />
    
</Grid>
  
</Border>
</UserControl>

  如上面的代码所示,UI上的很多元素我们都可以通过拖控件进行实现,有个功能需要自己简单的写一写代码,UI上面有一个功能就是你把鼠标放在图片上的时候会提示Company ID,这个功能通过ToolTip属性进行实现的。ToolTip属性是WPF所有元素的基类FrameworkElement的一个属性,所以我们可以在这些子元素当中直接使用。

  那么大家注意到,这个小功能在WinForm中我们要写一些代码,而在WPF就可以直接通过属性定制,所以在很多方面WPF对这些方面都做了封装和简化,也提高了我们的开发效率。

  案例总结

  通过上面的案例,我们主要认识到:如果不需要强大的图形和显示效果,WinForms和WPF 都能完成同一个需求,只是WinForms在设计的时候比较痛苦一些,并且没有单独把UI分立出来,所以很多时候都会和逻辑进行耦合;而WPF就不一样了,它用XAML来进行UI的设计,然后用后台C#或VB等语言来进行操作,这样就使职责进行了分立,使每个部分都发挥到了最好,同时也提高了开发效率。

  对于长期从事WinForms或者其他没有从事过ASP.NET等开发人员, 可能不太习惯XAML的这种开发习惯. 但对于ASP.NET 的开发者来说上手就比较容易一些了,因为在很多方面它和HTML有很多相似之处. 不过也没有关系,只要做了一段时间以后就会发现XAML代码是那么的有趣,以至于看到它就有一种亲切感!

  这个案例并不是介绍我们如何放弃WinForm和如何转向于WPF,只是想通过他们的异同进行一下简单的对比,大家都知道WPF的特长在于UI和逻辑的分离、强大的动画和图形效果,但是性能却是一个摆脱不去的瓶颈。而WinForm正好相反,它在性能上得到了比较好的体现,但在显示强大动画和图形效果以及一些高交互的效果方面就显得不能为力了,所以我们在做项目的时候应该有一个权衡,尤其是在现在的硬件和软件基础上。

  漫谈WPF开发

  谈到WPF的开发,就不能不说到MVVM,一说到MVVM,就会提及MVC、MVP等概念,那么这样一关联下来就会产生很多概念,到最后就很容易变成以概念来阐述概念,最终的结果可想而知,大家可能会一头雾水、不知所云,所以我用“漫谈WPF开发”这个小标题来阐述一下我对WPF开发的理解,当然只是自己对这些技术的总结和经验,错误之处在所难免,也希望大家能够谅解!

  从2007年接触WPF和Silverlight以来,也做过一些项目了,对他们也有一些自己的理解,当然在开发这些项目的过程中也在使用其他的一些技术做项目,比如WinForm、ASP.NET(ASP.NET MVC一个项目没做完就被终止)等等,感觉不论是采用什么技术,最基本的东西都不会变,比如对数据库和文件的访问、对日志和异常的处理、对报表的展现、对打印的实现、对性能的提升、对用户的友好等等。

  那么这些项目也为我们积累了不少经验,有技术上的也有其他方面的:

  · 为了应付项目需求的不断变化和项目的可扩展性,我们也会引入OO和设计模式;

  · 为了解除各模块和组件的耦合,我们也会利用IOC的思想解耦;

  · 为了让逻辑代码清晰且没有其他代码的干扰,我们也会采用AOP的方式进行代码重组;

  · 为了使项目的开发速度更快且更方便,我们也会引入ORM思想来加快项目的开发速度和可维护性;

  · 为了更好组织各层开发,隔开耦合,我们也会采用MVC、MVP、MVVM模式;

  · 为了提升用户的响应速度,我们会采用AJAX的方式来实现;

  · 为了降低系统的负载同时提高用户的响应能力,我们也会采用MSMQ或者SSB来组织消息队列;

  · 为了规范各系统的接口,提供一个统一的交互平台,我们也会采用SOA;

  · 为了降低服务器的负担和提高速度,我们也会自己写一套缓存;

  · 为了把产品做好,我们也会不断优化技术;

  · 为了能做好外包项目,我们会不需要任何高深技术;

  · 为了能得到客户满意老板好评,我们也会学会如何交流;

  其实归根到底就是要分清关系,理清思绪,既要处理好与机器的关系,也要处理好与人的关系,只有这样才能把产品或者项目做成功,我也在不断学习当中,所以如果大家有一些这方面的问题和建议,我们也可以互相讨论。

  前面不知所云的漫谈了一通,那么我们到底该怎么认识WPF项目的开发呢?我个人的观点是和其他技术一样,假如这是一个比较小的而且需求改动很小的项目,那么我不建议用一些高深的技术,因为它要的是马上看到效果和时间上的优势,所以应该抛弃我们的技术思想。当遇到一个比较大型的项目而且需求可能变动很大,那我们得慎重考虑系统的构架了,因为很多时候我们都会发现我们的系统无法再扩展了,这就是一个很大的“杯具”了。那么作为一个项目,我们怎样才能在事前做好呢?我觉得有以下几个方面:

  · 项目情况把握:首先我们要分析项目的背景、项目的目的、项目的前景、项目的需求、项目的客户、项目的实现难度、项目的规模、项目所使用的技术、项目的最终效果等因素,只有把握好了这些方面以后,我们才能做到对项目知根知底且游刃有余。

  · 项目团队把握:首先分析一下自己的团队成员组成结构,有没有领域分析人员?有几个架构师?有没有Team Leader? 有几个senor developer?有几个developer?有没有测试人员? 有没有项目配置管理员?有没有QA以及有没有类似的项目经验等。知道这些可以合理安排任务,这正是对自己团队的把握。

  · 开发模式把握:不论你是开发产品还是做项目,我们都需要采取一种适合的模式,那么什么叫适合呢?这个没有准确的答案,只有根据具体情况具体分析了,如果需求比较明确且系统较大,那我们就可以用传统的瀑布模型进行开发,只要客户能接受同时自己做好各方面的监控,应该问题不大;如果需求不是很明确且周期很长,我们可以用迭代的方式进行开发,这样客户也能更加明确自己的需求同时也能看到自己想要的效果。当然如果需求不明确而且有很多不确定因素,我们也可以采用TDD的方式进行开发,如果把握得好,这样慢慢也会形成一个比较好的项目。

  · 开发规范把握:作为一个多人开发的团队,没有一些规范是不行的,团队管理规范、项目管理规范、代码书写规范、开发流程规范、测试规范等等,这些都是要在开发之前定好,否则我们将会看到项目到处一盘散沙,无从管理。

  · 其他方面规范:其他方面的规范就很多了,比如开发环境的规范、测试的规范、文档的规范、部署的规范等等,这个可以根据具体项目进行裁剪。

  前面谈到了一些项目管理整体把握,总结就是大道至简、适可而止!那么我们如何才能在具体项目中引用一些其他技术呢?感觉思绪有点乱了,还是就此打住,等到了讲WPF具体项目或者具体技术的时候再讲,不然就真的一发不可收拾了。

0
相关文章