开发的技术细节本文就不谈了,作者只想从感性上谈谈学习和实际开发WPF的感想。
首先祝大家新年快乐,小生给大家拜个晚年!
两年前暑假,从百度百科上第一次了解WPF,被它的强大特性所吸引,当然最让我着迷和期待的就是“绚丽”二字。两年来,放弃了曾经的Winform开发知识,全面转战WPF,开发了两三个大型项目,七八个游戏,和一些小型应用程序。也从当年的热烈走向现在的稳重。因此,愿意更从感性的角度讨论关于WPF的一些感想。
本人只是在读研究生,且并非计算机科班出身,因此不足之处请海涵。
MVVM模式的思考
以前开发winform程序,界面和程序是死死耦合在一起的,当修改了变量命名,改个样式,或者做了一些其他修改(那会还不知道resharper),不得不花费很长时间来“擦屁股”,因此深之界面和逻辑解耦的重要性。
WPF很好的解决了这个问题,在设计之初就如此考虑,并引入了大名鼎鼎的MVVM模式。一开始不大了解,做得多了就懂了,一个ViewModel是不知道View的存在的,更利于分工合作,更利于单元测试。好处多得不得了。
可是,凡是总有弊端,MVVM确实适应于大量数据的展示,修改等“业务逻辑”,通过数据和命令绑定,触发器等等的功能,可以很好的适应这种需求。可是,并非所有程序都是这种类型的,试想,开发一款简单的游戏,你需要控制时间线,动画效果,复杂样式还有数不清的其他需求。此时,你会发现,除了直接用ViewModel操作View,别无他法。当然,如果硬要做分离的话,也可以,附加行为(AttachBehavior)就是干这个的,通过静态依赖属性,写一个附加类来做这个,可惜,代码复杂度成倍增加,需要较高的学习成本,把简单问题搞复杂了。
因此,我想说的是,MVVM是个好模式,可是别太追求完美,千万别捡了芝麻丢了西瓜,实在不行就耦合一下,这是一个很大的收获。
绑定到弱类型的xaml
我和所有程序员一样,喜欢强类型的安全感。
xaml绑定到了弱类型,好处在于更好的解耦,坏处在于没有了编译器和重命名工具的支持。我曾经用ReSharper修改变量名,从坐标名称”X“改成”PositionX“,于是,整个系统被这个重命名搞得一塌糊涂,让我修改了整整一天。运行时的绑定异常,比编译时更麻烦,好在有snoop.
不过,这个没办法。慢慢适应吧。
到底是依赖属性还是INotifyCollectionChanged?
常常需要在数据发生改变时通知界面(View)。于是便有了上面的问题。
依赖属性真是个好东西,通过玩”静态“二字,玩得真是漂亮。博客园里有不少介绍依赖属性和附加属性的文章,此处就不引述了。它算是WPF的根基,动画,资源,绑定,无处不在的依赖属性。
附加属性更是神奇,可以把属性记录在别的地方,”附加“这词用的很好。这让人想起了装饰器模式,动态增加属性和行为,只不过属性存储在了别的地方。
既然依赖属性这么强大,我们干嘛还累死累活的让数据实现INotifyCollectionChanged接口?还写一堆麻烦的数据更新通知?比如如下恶心的代码:
private short _BreathRate; public short BreathRate { get { return _BreathRate; } set { if (_BreathRate != value) { _BreathRate = value; OnPropertyChanged("BreathRate"); } } }
这样的代码在WPF中无处不在,恶心死人。可是,如果用依赖属性的话,也会带来问题,有如下原因:
1. 依赖属性的性能(肯定比原生的属性要慢)
2. 依赖属性不能跨线程访问!包括读!这个问题在多线程情况下真是要命
3. 必需继承于DependencyObject, 这不仅让你唯一的继承机会丧失,还引入了万恶的System.Windows命名空间,于是,你的未来代码移植会造成极大地困难。
因此,我们有如下结论:
算法和底层数据结构:毫无疑问,让它纯净一些,用INotifyCollectionChanged
界面相关:包括自定义控件,自定义效果等等,放心的用依赖属性吧,绝对是正确选择。
只有这样,界面逻辑解耦的愿望才能实现。
3D
WPF号称支持3D,但我依旧要吐槽它,除了让人无法忍受的效率问题,开发工具,教学资料的匮乏,都让WPF的3D处于难以为继的状态。据我所知,仅有3DTools这些简单的WPF的3D扩展工具,以及一些很简单的辅助设计工具。用WPF开发3D,除非万不得已,否则我不会用它。在这一点上,WPF完全可以向Unity3D学习。
第三方类库
WPF是个界面库,它天生就为良好的扩展性做好了准备。虽然不算多,但大部分需要的类库都有了,Avalondock, WPFToolkit, 物理引擎库,等等不一一列举了。这些库都比较新,不过很难看到WPF设计的完整软件作品,起码在国内看不到,他们都哪里去了???
性能
程序性能问题,是任何程序员都非常关心的。WPF的性能疑问,来自两个方面,一个是动画,一个是数据更新造成的UI更新。
我开发了几个游戏,发现比较复杂的物体移动,总会出现卡顿,那种令人不爽的“虚”感。使用更快的CPU和独立显卡可以较好的解决这个问题,可是在3317U这样的超级本平台上,程序运行起来风扇哄哄响,占用率达到一半。远远达不到unity3d这类3D平台上的性能和质量。同样效果的flash动画,也没有这种卡顿。这到底是怎么回事?
在数据绑定上,我曾经懒惰的通过OnPropertyChanged(“”)的方式更新全部数据,但造成了严重的性能问题,因此建议仅更新对应的数据。
设计和美学
这是个复杂的问题,有专门的学科研究,本部分仅浅尝辄止。
我的经验,WPF在2D层面不限制你的任何想象力。但我有如下建议:对于一般软件而言,避免不必要的花哨,提供统一直观的UI效果是非常重要的,动画等技术的存在,仅在于表达数据和信息本身,若造成用户干扰,则有”炫技“嫌疑的东西可完全不要。Expression Design套件的设计对我们有很好的借鉴,黑色底色,淡灰色的文字,让你专注于设计本身,而非工具。我们应该专注如何让用户更好的关注数据。
对于游戏或播放器等娱乐音乐而言,则设计思路有所不同。可以适当加入动画,在配色等角度可以更活泼,但一定注意整体设计的协调,与主题的搭配程度非常重要。
设计是个复杂的事情,没事可以逛逛很多平面设计论坛,都有很大的收获。
前景?
打个疑问号,表示该问题值得讨论。我没有真正深入业界,因此本节仅供参考。
06年WPF技术公开,在08-09年貌似达到高峰。据我所知,博客园的绝大多数关于WPF的文章都是这个时期发布的,Blend等工具的出现,大大改进了界面设计方便性。但貌似,我这个软件控也没有看到除了微软这套Studio之外的,任何以WPF开发的商业软件系统。360,QQ,各类音乐播放器等等都没有,只有QQ概念版基于WPF,可是之后也没有更新了。究其原因,大概是需要安装.NET 3.5甚至4.0以上版本,部署起来不甚方便。也与当前程序普遍WEB化不无关系,
但我依旧疑问,为什么在2010年之后,博客园很少有系统的WPF开发文章了?为什么到现在都没有客户端的WPF系统?它的前景究竟如何?
不过,学WPF一点都不亏,xaml,数据绑定,和AE,PR类似的时间线系统,和绝高的开发效率,这些知识可以很快的转移到其他相关领域。
结语
说了这么多,没用图片,也没拷贝大段代码,就是简单的聊聊。只是,在如今WEB化和移动化大行其道的情况下,windows桌面程序开发的价值又有几何?这难以估量,不过作为程序员,学习它,一点都不亏。
本文的任何见解, 欢迎大家讨论。