前言
一直想做一个windows phone 应用,一个完完整整的应用,包括设计、编码到测试。以前的博客中大都是一些小例子,小技巧,所以本文以一个具体的项目来分享我在开发windows phone 应用程序的心得,希望对大家以后的WP7征程会有一点帮助。
一、数据库准备
账户助手,也可以成为账户(Money)管理系统。大家看到管理系统,第一个想到的词汇是什么? 是不是诸如“信息管理系统”、“数据库”之类的词语,是的,我们账户助手中需要使用数据库。由于目前的Windows Phone 中没有内置数据库的支持(Mango更新会提供SQL-CE的支持) ,我们只能使用第三方提供的类库了。博客园的chenkai对Windows Phone 7 平台上数据库的使用做了一个很好的介绍。这儿我采用winphone7db.下图是winphone7db项目的截图
它实现的方法是使用xml进行存储,不知道大家对.Net 2.0中的DataTable和DataSet有没有什么印象,我以前经常接触这两个东东,其实他们也是基于XML的。下面我们来写一个简单的辅助类去操作winphone7db并利用Windows Phone 7 隔离存储空间资源管理器去查看我们存进去的数据长什么样的。
然后我们在界面中放置一个按钮,按钮的点击事件就是往数据库中插入数据,大致代码如下
运行后,我们来看看应用程序隔离存储空间中多了些什么(关于Windows Phone 7 隔离存储空间资源管理器可以参考我的博客)
右击AccountHelper.wp7Db.Model.Money 选择下载,使用UltraEdit或者其他文本编辑器打开后会发现里面的内容其实是一个xml,如下
note: NULL is auto generated by isolatedstorage explorer...
winphone7db测试项目源代码下载
数据库有了,接下来需要准备什么呢?对了,是程序框架!那么windows phone 应用程序使用神马框架最好呢?我的回答是MVVM Light....maybe it is different for you .
二、MVVM知识准备
2.1 MVVM简介MVVM的简介网上有很多资源,我就不重复了。我把自己的一点理解拿出来跟大家分享。MVVM,字母的全称想必大家都知道(Model-View-ViewModel)。我这里想要说明的一点就是MVVM一般是使用一个类去绑定整个页面的DataContext,这个类将在页面构造函数调用前被实例化(所以我们可以做一些初始化的事情...)。
2.2 MvvmLight简介
MVVM的框架很多,比如WPF最常用的Prism以及我们项目中用到的MvvmLight .
The MVVM Light Toolkit is a set of components helping people to get started in the Model - View - ViewModel pattern in Silverlight and WPF. It is a light and pragmatic framework that contains only the essential components needed.MvvmLight是开源的项目,我们可以查看其源代码,而且MvvmLight是基于MIT协议的,我们可以任意修改。并且MvvmLight提供了Visual Studio和Expression Blend的模板,简化我们的开发。
PS:MvvmLight的源代码在其目录GalaSoft.MvvmLight (NET35)下
2.3 MvvmLight之Command
Command是WPF和Silverlight中的重要特性之一, 但是在silverlight for windows phone 中对Command的支持并不友好,所以我们需要借助现有的框架去实现Command。熟悉WPF和Silverlight的朋友应该都知道ICommand的重要用处,MvvmLight中的Command也实现了这个接口。上图是MvvmLight中Command的初步实现方法,可以看到有两个类,一个普通Command,一个泛型的Command。分别有CanExecute(能否执行该命令,通常用于限制命令执行的条件),Execute(执行该命令)。RaiseCanExecuteChanged(是否能执行命令的条件发生改变)、RelayCommand(构造函数)。
第三个类图是扩展的Button,即往Button中附加Command及CommandParameter。(附件属性是一门“可怕”的技术,相当的神奇).
这个类的用处是将事件转换为命令,如果后面项目中用到再说。
2.4 MvvmLight之Messenger
大家用过MSN么,MSN的全称其实就是Messenger。大家用MSN来做神马,不是有QQ么。一位国外的朋友说道,外国人一般都用MSN。Messenger在MvvmLight中的作用就是用于View和ViewModel中的通信的。有童鞋会问,View和ViewModel不是通过数据绑定去沟通的么?绑定不是万能的,在某些时候绑定甚至会影响程序的性能,因为直接的赋值肯定比通过绑定引擎去赋值更快捷。Messenger可以在View或者ViewModel中注册(Register)一个"账号(token)"以及对于的处理委托(通常是对View或者ViewModel中的对象进行的操作),然后再ViewModel或者View中对其发送消息(Send),收到消息后,委托中相应的代码就会执行。大家可以联想CS游戏中的定时炸弹,我在你家里埋了个炸弹,然后我可以使用遥控器控制炸弹是否爆炸....来看下其实现方法,下图是Messenger的类结构图Messenger还有一个用处就是可以在ViewModel中使用MessageBox...
PS:我一开始真没理解为什么要用Messenger,接触过几个用法以及看了下源代码中的注释后稍微有所了解。大家有兴趣可以看看源代码,想想其中的道理。
2.5 小结MvvmLight是一款轻量级的MvvmLight框架,使用简单,功能强大,是居家旅行,开发WP7必备良器。
三、Expression Blend 知识准备
Blend是界面处理的利器,方便的生成XAML代码,我整理了一份 Expression Blend 知识锦分享 大家可以参考一下。这里由于篇幅原因就略去对Expression Blend的使用介绍了。另外国外的牛人整理的Blend系列也是很好 大家可以去看看 http://www.kirupa.com/blend_wpf/index.htm
四、需求分析与逻辑设计
在详细介绍如何去实现这个程序之前,有必要介绍下为什么要实现账户助手(即软件工程中的需求分析,很重要的一点)。我以前有记账本的习惯,即自己花了多少钱,花在那些地方。有个不错的软件,记账本(JZben),做的非常不错。但是由于记性不是很好,晚上可能就想不起来今天哪些地方花钱了,或者前几天花了多少钱…因为程序是安装在电脑上的,你可能只有某个时间才能操作它,这就是为什么要在Windows Phone 上实现类似软件的原因了,让你随时随地记录你资金(资金貌似有点夸大了…)的流向。由于是简单的记录,所以我这里尽可能的简单化,比如收支类型就只有收入和成本两种,其实还有很多的情况,如转账、借贷等等。
ok,需求分析简单确定了,我们有必要做这个软件,而且需求也不是很多,稍微整理下:
1. 记录花在什么地方
2. 随时随地记录(这个已经Over,windows phone is always with you)
3. 能出个月总收入、月总支出、月合计的数字
4. 如果能出个图表就更好了
5. 简单易用,漂亮大方(这个可能是所以软件都要求这样的)
Okay,我做的AccountHelper基本上就是按照上述需求来实现的。
4.2 逻辑设计
大部分程序员的主要任务其实就是将软件在逻辑上实现,很多时候我们程序员处理的就是逻辑问题。所以我们在写代码前需要将逻辑弄清楚,不然写的代码也是做无用功! 以下是AccountHelper的大致流程图:流程图有了,那么在项目中,我们选择哪些控件来呈现我们的数据呢,或者说我们的页面大概有哪些呢,具体见下图:
五、Coding
在软件工程中,Coding占的比例不大。但是在实际开发中,很多人往往花70%-80%的时间在Coding上。大部分人认为自己可以一边设计一边编码,而往往这种思想会让你事半功倍!我记得我以前有说过一句话“劳力者下,劳智者中,劳人者上”。很多程序员虽然号称做的是脑力活动,其实他们做的是劳力的工作。他们往往不愿意花时间在思考上,而是花在动手上:整个项目这儿看看,那儿瞧瞧。看了一点后就认为懂了,就想着照葫芦画瓢…哦,Dear….我以前也有类似的想法,我没吃过猪肉,还没见过猪跑么…“给我一个Demo,我能给你造10个类似的Demo”…..难怪山寨在国内这么流行….额,扯远了。以上那段话的意思是让大家多多注重需求分析和逻辑设计的重要性,如果你的逻辑错了,软件还可以改正回来,如果你的需求错了,那软件大都只能推倒重来…okay,下面进行Coding阶段,我尽量以最简洁的语言将大致的编码过程讲明白,如果不明白的,可以微博上找我私聊,哈哈.
右上图看,我们总共需要这些页面:MainView(首页),SettingView(设置页),NewChargeView(新建页)以及ChartView(图表页)。下面咱们逐个攻克之.(Note:我只会介绍大致思路,而不是详细的过程)
5.1 项目搭建
如上图,是主项目的大致框架,我们将不同作用的类放在不同的命名空间下,方便以后管理。主要的View同上的设计图。当然,这里需要引入一些命名空间。如下图所示:
5.2 首页实现
首页是一个全景视图控件,有四个项:菜单项、支出列表、收入列表和个人资料页。大致的效果如下图:收入以及成本列表其实就是两个ListBox,没什么难度,只要大家数据绑定正确,数据就能够正常显示,唯一的区别就是你的ListBox漂亮程度(P.S 美工不好,列表不怎么漂亮,嘿嘿)。
下面来看一下菜单项是如何实现的,我们看到菜单项有6个菜单,我这里采用绑定来实现,即在ViewModel中初始化这些菜单,并且这些菜单的Command都绑定的同一个,那么我们如果区分用户点击的是哪个菜单呢?我们知道Command是可以传递参数的,是的,就是通过CommandParameter来实现的。下图是Panorama项目的XAML代码:
可以看到是利用一个现有的turnstile实现,而这个turnstile是继承自ItemsControl的,所以这些菜单其实就是一个个ItemsControl。他又一个模板TuenstileItemTemplate,我们的绑定、Command都是写在模板中的:
前台XAML代码准备好了,我们需要在相应的ViewModel中准备相应的属性,从XAML中可以看到Menu的数据源是一个名为MenuList的东东。那这个东东是神马呢?我们这里采用的是在MVVM中采用的集合 ObservableCollection
我们在ViewModel中实例化属性,并给属性初始化,下面的代码即是初始化菜单:
相应的Command处理代码,我们根据传递过来的Type分别去执行相应的菜单命令
细心的朋友可以发现,在上面的代码中我们使用了Messenger,那么我们发消息给谁呢?上面的意思貌似是我想要在ViewModel中实现页面的跳转。那我们来看一下Messenger在哪注册的。我们需要在MainView的后置代码中注册这个Messenger,用以实现页面的跳转。
上面有详细的注释,相信大家能够看懂,下面来看一下我的资料页的实现。额,上图的收入支出都是乱写的...我们在App的后置代码中定义了一个全局变量,记录当前用户的资料,如用户名、当月收入、当月支出等等信息,申明一个属性
public static UserInfo CurrentUser { get; set; }
然后在构造函数中去实例化,去加载。
至于收入、支出列表很简单,就是两个ListBox,就不介绍了,下面再给出MainViewModel的构造函数:
5.3 新建页实现
新建页面是一个标准的PhoneApplicationPage,里面有一些可以输入的文本框,让用户输入信息,还有一个ApplicationBar,可以让用户保存数据。5.4 设置页实现
设置界面未实现~~~i am sorry~~~~~
六、Room for Improvement
由于是做Demo,加上时间精力有限,所以很多使用的功能都没有做,给出的源代码也仅仅是将大致的框架,里面可能会有许多问题。当然,你如果想要继续完善这个Demo,可以从以下方便进行:
6.1. 多账户支持
本来就想实现多账户的功能的,但是也算是给大家的一个小作业吧,其实就是分别存储即可。还有就是在启动程序时,判断当前是否存在账户,如果没有,需要弹出界面让用户创建账户;如果有多个账户存在,取当前setting中的账户。
6.2. 多币种支持
6.3. 多分类(现在只有收入、支出)
在现实生活中,肯定不是仅仅收入和支出的,还又可以细分出很多类别,如专注、借贷等等。大家可以将收入、支出更加细化为购物支出、饮食支出、工资收入、奖金收入等等类别。当然实现的话需要加不少东西哦,有兴趣的童鞋可以自己尝试实现。
6.4. 墓碑化处理
现在的项目中都没有做墓碑化处理,这肯定不对的,在实际项目中,我们必须做墓碑化处理:我们采用现成的类库去处理,也可以自己写代码去实现。
6.5 异常处理
后记
写这么长的文章还是头一回(所以特别佩服园子里那位专门写长文章的gay)....奈何昨晚看了《建党伟业》,激动了...所以今天早上抽时间把文章和demo做好了,当然里面有很多问题,因为需要你的完善...
Updated: Windows Phone 项目实战之账户助手升级 、快乐技术沙龙技术分享之账户助手