当前位置:编程问答 > wap >

WP7有约(四):课程全景

 

Written by Allen Lee

 

Do I trust some and get fooled by phoniness, or do I trust nobody and live in loneliness?

– Linkin Park, By Myself

 

化零为整

      前面三节课我们分别实现了课程表、作业本和笔记本三个主要功能,然而,它们的内容分散在三个不同的页面,试想一下,如果我想查看某门课下一次什么时候上课、今天有哪些作业要做以及今天记了哪些笔记,我就不得不在多个不同的页面之间来回切换了,这显然降低了应用程序的可用性(usability)!因此,这节课的任务是化零为整,把相关内容整合起来。

      在WP7里,内容的整合一般是通过"Hub"来实现的,比如说,People Hub、Pictures Hub、Music + Video Hub、Office Hub、Games Hub以及Marketplace Hub等都是典型的代表。那么,如何创建这样的页面?非常简单!右击Projects面板里的项目节点,选择Add New Item:

\

图 1

在弹出的New Item对话框里选择Windows Phone Panorama Page,输入页面的名字,然后按OK:

\

图 2

此时,Expression Blend会为你创建一个Panorama页,里面包含了两个Panorama项。在Properties面板上把Panorama控件的Title属性设为"组织行为学",接着,添加一个Panorama项,然后,把页面上的三个Panorama项的Header属性分别设为"课程概况"、"今天笔记"和"今天作业":

\

图 3

这三个Panorama项分别用于显示当前课程的基本信息、今天记录的笔记以及今天要做的作业。接下来,我们将会详细探讨每个Panorama项的设计。

      首先是"课程概况",我希望它能告诉我每周星期几有课以及下节课的相关信息:

\

图 4

看到这里,你可能会问,这是怎么弄的?你可以在Panorama项里放置两个TextBlock,也可以放置一个ListBox,你的决定将会影响到后面的实现,这里没有谁对谁错,你要做的只是权衡利弊,做出决定,然后承担责任。这里选择了后一种做法,主要是考虑到将来添加其它信息时可以更加方便。

      接着是"今天笔记",要显示今天的笔记并不难,也就是一个ListBox的功夫:

\

图 5

然而,仅仅这样就够了吗?我们知道,新建和查看是最常用的两项操作,可以满足用户绝大多数时候的需求,我们应该尽可能让用户最快地接触到常用的功能,这意味着我们可以考虑把新建操作集成到这里,但完整的新建操作需要打开NewOrEditNotePage页才能完成啊,而CourseHubPage页的设计原则是尽可能让涉及到的操作"就地完成",并且用户可以马上看到结果,怎么处理?要回答这个问题,我们得先搞清楚用户在什么情况下会通过CourseHubPage页来新建笔记。我们知道,用户在新建笔记的时候需要提供笔记内容和笔记标签,然而,只有笔记内容是必须提供的,笔记标签的提供可以延后,如果用户要在极短时间内新建笔记,比如说在课堂上,那么暂时忽略笔记标签,只输入笔记内容显然会极大地加速整个操作过程,换句话说,用户只需一个TextBox和一个Button就可以完成新建操作:

\

图 6

需要注意的是,TextBox的TextWrapping属性的值默认是Wrap,这是为了让TextBox能够根据内容的长度自动调整自身的高度,然而,这个好处在这里会导致下面的ListBox被挤压,从而使得笔记内容的显示空间减少,这显然不是我们希望看到的,因此我们需要把TextBox的TextWrapping属性的值设为NoWrap。

      最后是"今天作业",出于相同的理由,我也为它配备了新建功能:

\

图 7

然而,仅仅这样就够了吗?当然不够,首先,用户无从知晓哪些作业还没完成,其次,当用户完成一项作业时,很自然地想把它标记为已完成,然而,就目前的设计而言,用户得先退回主菜单,然后进入作业本找到并编辑这项作业,这个繁琐的过程无疑降低了应用程序的可用性。有没有办法可以简化这个过程?我们知道,作业的完成状态是通过IsCompleted属性来标识的,这个属性的类型是bool,一般而言,如果我们要在用户界面上表达这个类型的数据,我们会选择CheckBox,因此,我们不妨为每项作业配备一个CheckBox:

\

图 8

这样,用户既可以直观地了解作业的完成状态,又可以轻易地更改作业的完成状态,而我们唯一要做的只是创建一个双向数据绑定!

 

连接前端和后端

      有了用户界面,接下来就是为它创建对应的ViewModel类了。首先,在ViewModel文件夹里创建一个CourseHubViewModel类,并让它继承NotificationObject类:

\

代码 1

接着,创建以下三个属性:

\

代码 2

它们将会分别绑到课程概况、今天笔记和今天作业上的ListBox。那么,我们应该如何初始化它们呢?

      Assignments属性的初始化最简单,因为Assignment类里有个StartDate属性,我们可以根据这个属性在CouseHubViewModel类的构造函数里筛选出今天的作业:

\

代码 3

但是,Note类没有类似的属性啊,怎么办?创建一个吧:

\

代码 4

这样我们就可以像筛选作业那样筛选笔记了:

\

代码 5

最麻烦的是Overview属性,它需要我们重新组织/聚合课程的信息,比如图4的第一条信息——"逢星期一、星期二、星期五有课",其中"逢XXX有课"是固定部分,"星期一、星期二、星期五"是可变部分,这部分信息保存在Course对象的Day属性里,我们可以通过LINQ查询课程表里特定课程的所有Course对象,然后提取它们的Day属性,并按照我们期望的格式聚合起来:

\

代码 6

至于第二条信息,我们得先找到下节课的Course对象,怎么找?想想看,如果我们手头上有一份课程表,我们会怎么找呢?我们会先看看明天有没有这节课,如果有,那就是它了,如果没有,看看后天有没有,如此类推,下星期的今天为止。我们可以模拟这个过程查找下节课的Course对象:

\

代码 7

需要说明的是,某个课程(Course对象)星期几有课是以字符串的形式表示的,而某天(DateTime对象)星期几却是以DayOfWeek枚举的形式表示的,因此我们需要一个GetChineseDayName方法把DayOfWeek枚举转换成对应的中文字符串:

\

代码 8

现在,请思考一下,GetChineseDayName方法有没有可能抛出ArgumentException异常?如果有,什么情况下会抛出这个异常?如果没有,为什么?好了,找到下节课之后,我们就可以着手相关信息的聚合了:

\

代码 9

值得提醒的是,这里的做法是不具备多语言扩展的,不过,就目前而言,这已足够了。

      接下来,我们将会实现"今天笔记"的新建操作,从用户界面上看,这个功能是由一个TextBox和一个Button组成的,前者只需配备一个对应的字符串属性:

\

代码 10

至于后者,根据上节课的经验,我们需要为它创建一个NewNoteCommand属性:

\

代码 11

然后在构造函数里把它初始化为一个DelegateCommand对象:

\

代码 12

DelegateCommand类的构造函数接受两个参数,第一个是执行这个命令时将会调用的代码,第二个是判断这个命令能否调用的代码。当用户单击按钮时,我们需要根据当前课程、笔记内容以及

补充:移动开发 , Windows Phone ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,