Windows Phone 7

Windows Phone 与云 - 简介

Ramon Arjona

我正在学习用西班牙语进行阅读和写作。由于我居住的位置有先天条件,我可以尝试阅读许多公共场所出现的双语标记来练习西班牙语。问题是,有些时候我会被某个特定词语困住,弄不清楚意思,或者完全无法理解整句话。而且,也很难保证在没有相应的英语翻译可供参考的情况下,我是否理解了所阅读的内容。我可以随身携带西班牙语-英语词典,但是翻遍词典也只是模棱两可。

因为我的手机似乎总不离手,所以我实际上希望轻松地使用手机来帮助进行翻译。用手机访问 Bing,然后使用基于云的 Microsoft Translator,这样做会有所帮助,但要进入翻译屏幕需要大量的按键操作。如果有某种方式可以方便地在手机上使用翻译功能,那就万事大吉啦。现在,随着 Windows Phone 7 的横空出世,您再也不必为此发愁了。

本文对开发 Windows Phone 应用程序进行了介绍,并演示了如何将此类应用程序与云中的 Web 服务绑定。您应该对 C# 和 Visual Studio 有一定的了解,如果您或多或少有一些使用可扩展应用程序标记语言 (XAML) 开发应用程序的经验(但并不作要求),将非常有帮助。我使用的是 Windows Phone 工具的社区技术预览 (CTP) 四月升级版。在您阅读本文时,内容可能已经发生了更改,因此,请访问 developer.windowsphone.com,阅读最新的文档并下载最新的工具。

首先要做的是:获取一个应用程序 ID

如果您要与 Translator 或任何 Bing Web 服务进行交互,第一步就是获取一个应用程序 ID。应用程序 ID 由服务 API 用来验证来自已注册 Bing 应用程序开发人员的请求。

请访问 bing.com/developers/createapp.aspx,接着使用您的 Windows Live ID 登录。然后填写表单,该表单会要求您提供应用程序的名称和说明,以及诸如您的公司名称和电子邮件地址之类的详细信息。当这些 API 发生了更改(例如推出新版本或者旧版本脱机)时,就会使用您的电子邮件地址来通知您。尤其对于 Translator API,在撰写本文档时已说明,旧版本将在新版本发布后持续服务 90 天。

接下来,请阅读使用条款,选中复选框以表示您接受这些条款,然后单击“接受”按钮。随即会进入一个页面,您新创建的应用程序 ID 就显示在该页面中。您可以随时返回此页面进行查看,但我通常在首次创建应用程序 ID 时,会将它复制并粘贴到应用程序的源文件中。

对于您打算在应用程序中使用的任何 Web 服务,请务必阅读该服务的使用条款。请静下心来仔细阅读,而不要一扫而过,尤其是当您打算通过 Marketplace 向用户分发您的应用程序时更是如此。对于您的客户,您有责任了解由提供您的应用程序所使用服务的合作伙伴设定的服务水平目标和其他条件。因此,无论您的应用程序是否使用了 Microsoft 或任何其他方提供的服务,都应确保您阅读并了解该服务的使用条款。

既然您已经有了应用程序 ID,我们就可以开始开发手机翻译应用程序了。

定义方案

在开始创建我的第一个应用程序之前,我了解了一下市场上一些成功的移动应用程序。我对一些用于 Windows 电话以及其他智能手机的应用程序进行了了解,想尝试搞清楚一款真正成功的移动应用程序的成功秘诀。我阅读了许多产品评论,采访过许多用户,也打扰过许多朋友,让他们把自己的手机交给我体验。

做完所有这些调查之后,我得到的结论是:一款成功的移动应用程序的关键在于简便性。每种流行的应用程序都实现了一种或两种主要的用户方案,并且都实现得非常完善。例如,我发现了一整类应用程序,它们的唯一用途就是产生各种粗俗的噪音。实际上,它们本来的功能就是在手机上重现呵斥声或肠胃胀气声。用户似乎对这些很感兴趣,至少足以让他们付费在自己的手机上加载这些应用程序。

类似地,还有一些应用程序,它们可以模拟投掷骰子的游戏,推荐享用晚餐的餐馆,甚至可以为推荐的晚餐计算小费。所有这些应用程序都有一种核心的用户方案,并以一种简便、直观的方法来执行该方案。这种方法并非任何特定品牌的智能手机所专有。developer.windowsphone.com/windows-phone-7 上发布的《Windows Phone UI 设计和交互指南》已经要求我们坚持打造优美、直观用户体验的设计理念。

因此,当我开始开发自己的翻译应用程序时,重点是要关注我真正希望该应用程序实现的功能,而不是其他方面。为此,我首先需要对自己希望实现的功能有清晰的认识。脑海中有了此认识之后,我就可以抵制诱惑,不会去添加炫酷新功能。这样的新功能虽然有趣,但对主要用户方案毫无用处。我决定了,我的应用程序要实现的应该是英语和西班牙语之间的互译功能。这款应用程序必须可以轻松地切换翻译模式(从西班牙语到英语或英语到西班牙语),而且只处理单个单词或简单的句子。另外,由于我只关注西班牙语和英语,因此我的应用程序将忽略其他语言。

构建应用程序

要开始构建翻译应用程序,请打开 Visual Studio Express 2010 for Windows Phone。依次选择“New project...”(新建项目...)、“Windows Phone Application”(Windows Phone 应用程序)。此操作会打开默认的 Windows Phone 项目,并显示一个由以下两部分组成的屏幕:标题和内容。这两部分用 XAML Grid 对象来表示,我们可以利用该对象定义一系列的行和列,然后在其中放置诸如按钮和 TextBlock 之类的子 UI 元素(请参见图 1)。

图 1 默认 Windows Phone 项目(包含“显示视图”和“代码视图”)

首先,在设计器中选中应用程序名称和页面标题,对这些 UI 元素进行编辑。此操作会在设计器的代码视图窗口中突出显示相关的 XAML,向您展示需要编辑的元素。接下来,打开工具箱,然后向页面上较低的网格(称为 ContentGrid)拖放一些 UI 元素。选择一个 TextBox(用于输入要翻译的单词),然后选择一个 TextBlock(用于呈现翻译的内容)。最后,添加两个按钮(请参见图 2)。

图 2 添加 TextBox、TextBlock 和 Button UI 元素

一个按钮用于执行翻译功能,另一个按钮用于从西班牙语到英语或相反方向切换翻译方向。

XAML:时尚 UI

Windows Phone 7 用户体验的核心是名为“Metro”的设计系统代码,而根据 Metro 系统实现 UI 的核心就是 XAML。如果您之前使用过 Silverlight 或 Windows Presentation Foundation (WPF),则您很可能熟悉 XAML。如果您没有用过,则本部分将进行简要介绍。

XAML 是一种以声明形式构造 UI 的方法,可以使您将应用程序的逻辑与外观严格分离。例如,您会注意到应用程序主页面的代码包含在 Mainpage.xaml.cs 中,而应用程序的基本布局的代码则包含在 Mainpage.xaml 中。与传统的 Windows Forms 开发不同,这里的应用程序代码与应用程序的 UI 布局不存在任何混合。应用程序中的每个 UI 元素都建模为 XAML 文件中的 XML 元素。

这样做的好处在于,它可以在一位设计人员处理应用程序的逻辑时,允许另一位设计人员独立地处理应用程序的外观。例如,既然我们已经勾勒出翻译应用程序的基本 UI,就可以将 XAML 交由 UI 专家来处理,而我们则可以继续处理代码。UI 设计人员不需要知道我的应用程序实现的任何内容,我也不需要知道他选择的调色板的任何情况。

当然,我也没有 UI 设计人员的任何预算,但我有 MSPaint,它足以演示更新我的应用程序配套的图形资源有多么容易。

给 Translator 打造一个全新的图标

双击创建项目时自动添加到项目的默认 ApplicationIcon.png。此操作可打开我的图像编辑软件,即我的开发计算机上的 MSPaint。将令人乏味的齿轮状图标替换为大写字母 T。然后清除黑色背景,将背景填充为纯粉红色。大家可能会不喜欢我的图形设计,但我喜欢(请参见图 3)。

图 3 使用 MSPaint 创建的新项目图标

为了查看更改情况,单击启动按钮,将应用程序部署到 Windows Phone 7 仿真器中。如果您使用过以前版本的 Windows Phone 仿真器,则会立即感受到开发人员体验有了大幅提升。使用 Windows Phone 6.5 仿真器可能会非常麻烦,涉及到启动以及向仿真器附加调试程序的许多手动配置步骤。在 Windows Phone 7 开发环境中,只需单击绿色的启动按钮即可实现所有操作。我对仿真器加载和显示应用程序主 UI(请参见图 4)的速度十分满意。

图 4 Windows Phone 7 仿真器显示的应用程序

为了查看应用程序图标,我从主 UI 中退出,然后导航至仿真器的主屏幕。即可看到 Translator 图形,显示效果还不错(请参见图 5)。

图 5 在仿真器中查看新应用程序图标

应用程序清单

应用程序图标是在名为 WMAppManifest.xml 的文件中定义的,该文件位于项目的 Properties 文件夹中。要重命名应用程序的图标,请更改项目中 ApplicationIcon.png 的名称,然后确保在 IconPath 元素中反映该更改:

<IconPath IsRelative="true"
   IsResource="false">myicon.png
   </IconPath>

如果应用程序无法找到自己的图标,则在运行时会分配默认图标,默认图标看起来就像一块黑色背景上有一个白色圆圈。

该文件的另一个需要检查的元素是 Capabilities 元素,该元素包含您的应用程序希望使用的特定功能。最好只请求您的应用程序真正需要的功能。如果您通读该文件,您会看到该文件中包含大量不大可能在我们的翻译应用程序中使用的功能。

例如,ID_CAP_GAMERSERVICES 表示应用程序需要与 XBox 游戏 API 进行交互,ID_CAP_LOCATION 功能表示应用程序需要利用设备的定位功能,ID_CAP_PUSH_NOTIFICATION 表示应用程序需要与 Windows Phone 7 的推送通知功能进行交互。所有这些功能都很棒,但我们的应用程序并不需要,因此可以去掉这些功能。实际上,我们可能只需要 ID_CAP_NETWORKING 功能,该功能表示应用程序需要使用网络来发送和接收数据。

Microsoft Translator API

Microsoft Translator 提供了三种 API。SOAP API 可以为使用者提供强类型化和易用性。AJAX API 主要供希望在其 UI 中嵌入翻译功能的网页开发人员使用。当 SOAP 和 AJAX API 都不适用时,HTTP API 非常有用。

我们将选择 SOAP 接口,因为该接口最容易实现我们的目的。转到“解决方案资源管理器”,然后右键单击“引用”。然后选择“添加服务引用”,输入 Translator API 的 SOAP 接口的端点:http://api.microsofttranslator.com/V2/Soap.svc。在命名空间文本框中,将该服务端点命名为 TranslatorService,然后单击“确定”(请参见图 6)。

图 6 添加 SOAP 服务引用

Visual Studio 将为您代劳其余的工作,生成 SOAP 接口客户端代码。

现在向您的应用程序添加一些代码。在应用程序的 MainPage 类声明中,将应用程序 ID 和引用添加到 TranslatorService 客户端:

string appID = <<your appID>>;
  TranslationService.LanguageServiceClient client = 
    new TranslationService.LanguageServiceClient();

IntelliSense 显示翻译服务有许多有趣的方法可用。首先要注意的是,所有这些方法都是异步的。这一点很有用,因为我们在等待网络操作完成的过程中,没有任何充分的理由去阻止客户端应用程序。这意味着,我们需要为我们执行的每个特定操作注册一个委托。在本例中,我们只对 LanguageServiceClient 提供的 TranslateAsync 方法和 TranslateAsyncComplete 事件感兴趣,但其他方法一定也很有趣。让我们来了解一下这些方法,看看它们是否适合我们的用户方案。

其中比较突出的两个方法是 GetLanguagesForTranslateAsync 和 GetLanguageNamesAsync。第一个方法可以提供 Translator 服务支持的语言代码列表。通过调用此方法,您可以看到西班牙语的语言代码为“es”。对于给定的一组语言代码,GetLanguageNamesAsync 方法可以返回一个按照给定区域设置本地化过的语言名称列表。例如,如果您将“es”作为区域设置和语言代码传递到此方法,则将返回字符串“Español”。如果我们要实现多语种翻译功能,则这两种方法将非常有用。

另一个有趣的方法的名称为 SpeakAsync。该方法可以接受一个字符串和一个区域设置,然后返回指向一个 WAV 文件(单词的地道发音)的 URL。这项功能酷极了。例如,我可以键入一个字符串,获得其翻译,然后将该字符串传递给 SpeakAsync 方法获取一个 WAV 文件,接着可以利用此文件用西班牙语与他人进行交流。或者,当我不确定某个特定词语的发音时,我可以使用 SpeakAsync 方法来听一下该词语的地道发音。

这些功能超酷,因此实在忍不住要将它们放到应用程序中。但是,现在我们得挺住,需要将全部精力投入到实现我们最初制定的用户方案当中。如果脑海中有这种清晰的认识,就能够更轻松地抵挡“再多添加一项功能”的诱惑。我确信在将来的某个时候,我肯定会使用 Translator API 中提供的这些功能,但不是现在。

绑定代码来制作我们的翻译应用程序非常容易。首先,我们要为 TranslateCompleted 注册委托:

client.TranslateCompleted += new
  EventHandler<TranslationService.TranslateCompletedEventArgs>
  
(client_TranslateCompleted);

然后,我们要实现 TranslateCompleted 事件处理程序,该处理程序可以将 TextBlock 的文本设置为翻译后的文本:

void client_TranslateCompleted(object sender,
   TranslationService.TranslateCompletedEventArgs e)
 {
   TranslatedTextBlock.Text = e.Result;
 }
We wire up the button to submit the text we’ve entered for translation:
 private void TranslateButton_Click(object sender, 
   RoutedEventArgs e)
 {
   client.TranslateAsync(appID, TranslateTextBox.Text, fromLanguage,
     toLanguage);             
 }

接着,我们要为第二个按钮添加一些简单的代码,使它可以在两种翻译模式(“西班牙语到英语”或“英语到西班牙语”)之间进行切换。此按钮可以管理一个全局状态变量,并且更改翻译按钮的文本来指示该状态。

最后,我们将该应用程序部署到仿真器中进行测试。现在,我们只需几行代码和大约一小时的开发时间,就获得了一个功能完整的翻译应用程序。

扩展翻译应用程序

尽管这款简单的翻译应用程序已经很不错了,但我们还可以通过扩展我们的用户方案进行进一步完善。如果我们能够按照符合 Metro 设计规范的方式向我们的应用程序中绑定 Translator API 提供的更多语言,那就太棒了。如果能够清除控制翻译方向的按钮,用一种更简便、直观的方式来控制翻译方向,那就更完美了。无论我们怎么做,都必须为使用手指与设备进行交互的用户提供友好、快捷、简便的用户体验。

那么,我们该怎么做呢?我们使用默认的列表项目构建一个应用程序。启动一个新项目,然后选择“Windows Phone List Application”(Windows Phone 列表应用程序)。此操作将进入默认屏幕,其中的 ContentGrid 会显示一个 ListBox 控件。该 ListBox 将用六种语言(即我们要将文本翻译成的目标语言)替换虚拟文本(请参见图 7)。

图 7 默认 Windows Phone 列表应用程序

我们要对 MainViewModelSampleData.xaml 文件进行编辑,该文件包含在项目的 SampleData 文件夹中。您会看到一些类似如下代码的 XML:

<local:ItemViewModel LineOne="design one" LineTwo="Maecenas praesent accumsan bibendum" LineThree="Maecenas praesent accumsan bibendum dictumst eleifend facilisi faucibus habitant inceptos interdum lobortis nascetur"/>

您可以通过编辑该 XML,来更改 ListBox 的设计时视图,使之包含我们要处理的所有语言:西班牙语、德语、英语、葡萄牙语、意大利语和法语。请注意,在您保存此文件之后,设计时视图就会反映您所做的更改。这是因为 ListBox 控件与 MainViewModelSampleData.xaml 中定义的 Items 元素是数据绑定的。这一点由 ListBox 控件的 ItemsSource 属性控制。

您还可以在运行时更新 ListBox 的内容。如果您仔细查看 Visual Studio 生成的文件,您会发现一个使用占位符数据填充的可观察集合 <ItemViewCollection>,这些数据与 MainViewModelSampleData.xaml 文件中包含的数据类似。例如,如果我希望根据 GetLanguageNamesAsync 方法返回的语言在 UI 中动态地生成语言列表,就需要编辑 MainViewModel.cs 文件来填充 Items 集合。现在我更愿意指定一个静态语言列表,只对 ItemViewModel 对象集合直接进行编辑。现在,当我们运行该列表应用程序时,应该会看到一个有点类似图 8 的 UI。

图 8 列表应用程序 UI

当用户触碰其中一个按钮之后,就会进入一个详细信息页面,该页面实际上与我们的 SimpleTranslator 的 UI 是一样的。该页面包含以下控件:一个用于输入要翻译的文字的 TextBox,一个用于显示翻译后的文本的 TextBlock,以及一个用于提交翻译命令的按钮。不过,我们不用添加另一个按钮来管理翻译的方向,我们将依靠 Translator API 来实现这一功能。我们的 SimpleTranslator 应用程序的双向翻译功能在这种多语言方案中是没有意义的,而添加额外的 UI 层又会使应用程序运行迟缓而不流畅。值得庆幸的是,Translator API 提供了一种可以自动检测传入的语言的方法。

我们先添加一些代码来调用翻译客户端的 DetectAsync 方法,传入我们要翻译的文本,然后再从 DetectAsyncComplete 事件处理程序调用 TranslateAsync。现在该事件处理程序将如下所示:

void client_DetectCompleted(object sender, 
  TranslationService.DetectCompletedEventArgs e)
{
  string languageCode = e.Result;
  client.TranslateAsync(appID, TranslateTextBox.Text, fromLanguage, tolanguage);
}

我们可以从用户选择的按钮知晓我们要翻译成的目标语言。 我们可以从 Translator API 自动检测的结果知晓我们要翻译的源语言。 我们用了不到一小时的编码时间,就创建了一款简易多语种翻译应用程序,用户只需按两下(不计算键入操作)就可获得翻译。

简便性

简便性是 Windows Phone 7 开发的核心。 一款应用程序应专注于实现一种用户方案,而且要实现得很完善。 利用 Windows Phone 7 SDK CTP 自带的工具可以轻而易举地交付操作简便、功能强大的应用程序。 同时我们已经看到,与云交互非常容易,开发人员只需投入少量时间,即可将 Microsoft Translator Web 服务绑定到 Windows Phone 应用程序中。 借助一些熟悉的工具(如 Visual Studio)和明确的规范(如 Metro),Windows Phone 可以和云一起共同为开发人员和用户开辟一片充满新机遇的广阔天地。

Ramon Arjona 是 Microsoft Windows 团队的一名高级测试主管。

衷心感谢以下技术专家对本文的审阅:VikramDendiSandor Maurice