Flashcards.Show – 规划跨平台解决方案





5.00/5 (2投票s)
Flashcards.Show – 规划跨平台解决方案
以下是 Yochay Kiriaty 的另一篇文章,关于我为 Microsoft 完成的一个涉及 WPF、Silverlight、Windows Phone 7 和 Windows Azure 的项目。
如果您想了解更多详细信息,请务必参加我即将在 SDP 2011 大会(两天后!)上进行的演讲。
我最近发表了一篇关于 适用于 WPF、Silverlight 和 Windows Phone 的 Flashcards.Show 第二版 的博客,其中介绍了 Flashcards.Show
应用程序。我不会(再次)回顾该应用程序,但我确实想谈谈我们是如何开发该应用程序以及如何设计代码库以支持多个客户端的。
Flashcards.Show
的第一个版本是一个 Windows (WPF) 应用程序。该应用程序最初由 IdentityMine 设计,并使用了一些 Windows 7 功能,例如多点触控和任务栏集成。虽然第一个版本很棒,但我们希望通过让用户能够分享他们创建的牌组来增加其价值。因此,当我们开始开发第二个版本时,我们寻求功能和技术解决方案,以实现牌组共享场景的易用性,以及代码的开发和维护的易用性。
牌组共享场景的易用性通过让用户只需单击一个按钮即可开始共享过程,再单击另一个按钮即可发送牌组来实现。在幕后,应用程序与 Windows Azure Flashcards 服务通信并上传牌组。为简单起见,我们选择使用默认的电子邮件客户端应用程序作为发送电子邮件的方式。生成的预填充电子邮件包含一个指向 Silverlight 播放器的链接,该播放器允许电子邮件收件人查看和与附加牌组交互。如果您想亲身体验,可以点击此链接。电子邮件还包括有关如何将牌组下载到您的 Windows Phone 应用程序以及如何安装 (使用 ClickOnce) WPF 应用程序的信息。
在 WPF、Silverlight 和 Windows Phone 之间共享代码
设计好牌组共享后,我们的下一步是构建 Silverlight 查看器。我们知道我们将把 Windows Phone 作为下一个目标平台,因此我们的第一个决定是确保运行时兼容。这促使我们决定将查看器构建为 Silverlight 3 而不是 Silverlight 4 应用程序。虽然这个决定让我们花费了几天时间将 SL4 功能实现在 SL3 代码中,但在 Windows Phone 开发阶段它获得了回报。
第二个决定是尽可能多地共享代码库,我们做到了。Flashcards.Show 源代码 包含一个解决方案文件,其中包含所有“客户端”(WPF、Silverlight 和 Windows Phone)项目。如果您感兴趣,可以在 WindowsAzureService 文件夹中找到另一个解决方案文件,其中包含所有 Flashcards.Show
项目,包括 Windows Azure(解压 zip 文件后)。现在,我们将重点关注客户端项目
FlashCards.ViewModel.WPF
– 包含 Windows 应用程序中使用的 MVVM 架构的视图模型部分FlashCards.ViewModel.SL
– 包含 Silverlight 应用程序中使用的 MVVM 架构的视图模型部分FlashCards.ViewModel.Phone
– 包含 Windows Phone 应用程序中使用的 MVVM 架构的视图模型部分FlashCards.UI.WPF
– 包含主要的 Windows 应用程序,包括管理员模式和游戏模式FlashCards.UI.SL
– 包含 Silverlight 应用程序,包括不同的页面和资源FlashCards.UI.Phone
– 包含 Windows Phone 应用程序,包括不同的页面和资源
查看上面的列表,您可能会问自己,不同的 ViewModel
项目和 UI 项目之间是否存在重复。首先,我们必须针对目标框架进行编译。用于 WPF ViewModel
.NET 3.5 的程序集不受 Silverlight 或 Windows Phone 支持。除了 Silverlight 程序集,Silverlight 3 也未完全受 Windows Phone 支持。因此,您别无选择,只能编译到所需的目标 CLR。
但这远不止于此,尤其是在 ViewModel
项目方面。由于所有客户端基本上共享相同的数据模型,因此它们都具有相同的应用程序逻辑、显示相同的游戏并遵循相同的游戏规则。因此,Silverlight 和 Windows Phone 视图模型项目都包含指向 FlashCards.ViewModel.WPF
视图模型项目大部分内容的链接。WPF 视图模型包含卡片组的数据模型 (cardDeck.cs),该模型由单个卡片 (cardPair.cs) 组成,而单个卡片又由卡片的两面 (card.cs) 组成。该模型包含关于放置在每张卡片上的项目类型(文本、图像、声音、视频、URL)的元数据 (MetaData
) 信息。游戏逻辑也是视图模型的一部分,如您在 LearningGameViewModel.cs 和 MatchingGameViewModel.cs 中所见。请随意进一步探索代码。
如果您查看 Flashcards.ViewModel.SL
和 Flashcards.ViewModel.Phone
项目,您会发现它们 几乎
完全相同,并且这些项目中的代码文件只包含指向原始 WPF 视图模型文件的 链接
。
然而,更仔细地审查 Flashcards.ViewModel.SL
会发现一些差异。例如,Silverlight 视图模型没有 Taskbar.cs 文件,因为它不像 WPF 应用程序那样与 Windows 7 任务栏集成。Silverlight 版本也不包含 DeckPackaging.cs 文件,因为我们不允许 Silverlight 查看器编辑和上传牌组到 Windows Azure 服务。
我们省略了在 Silverlight 和 Windows Phone 解决方案中不具备功能的文件和类。您可能需要注意的是,Flashcards.ViewModel.Phone
与 Silverlight 视图模型是相同的。
但是还有一些额外的变化反映了不同平台之间的差异。在视图模型项目中,您可以在 MainViewModel.cs 文件中找到它们。此文件的 WPF 和 Silverlight 版本彼此之间差异很大。Windows Phone 代码嵌入在 Silverlight 项目中,我们使用 WINDOWS_PHONE
和 SILVERLIGHT
条件编译符号来区分两者。查看 MainViewModel.cs 文件,您会注意到编译时条件语句,例如:#if WINDOWS_PHONE
我们决定使用编译时符号而不是在手机项目中创建一个完整的 MainViewModel.cs 文件新副本的原因,是由于这样一个简单的事实:虽然两者之间存在差异,但它们很小且相对容易封装。
例如,Windows Phone 应用程序可以将牌组保存在本地存储中,这是我们在 Silverlight 中不使用的功能(尽管可能)。这引入了一整套新功能,例如通过网络从隔离存储获取牌组,这可以为 Windows Phone 实现封装,并从主视图模型逻辑中抽象出来。我们只需确保主视图模型接收其内部数据模型所需的 信息,并且当代码在 Windows Phone 上编译和运行时,我们确保以对主视图模型逻辑透明的方式封装附加功能。
例如,StartLoading
函数是为 Silverlight 和 Windows Phone 实现的。虽然代码性质相似,但在 Windows Phone 实现中,您会注意到我们需要进行额外的操作。例如,在 webClient_OpenReadCompleted
方法(已调用...)中,我们不仅将流返回给视图模型,还将牌组写入隔离存储。在写入过程中,我们会显示进度报告,因为此类操作在 Windows Phone 上可能需要一些时间。
另一个例子是 Windows Phone 中用于控制应用程序页面之间导航的私有 _instance_PropertyChanged
方法,而在 Silverlight 版本中,我们只是替换用户控件而不是完整的页面。
经验总结
- 尽可能使您的数据模型与技术无关
- 在您的视图模型中,将应用程序逻辑中处理数据(模型)的方式与应用程序流(屏幕、页面等)(视图)的方式分开。这将使为不同平台引入不同的行为和代码变得更容易,就像我们为 Windows Phone 和 SL 所做的那样
共享 UI (XAML) 难度大
这引出了我们下一个话题:共享 UI 和 XAML。虽然共享 View-Model 相对简单,但共享 UI 则完全是另一回事。
首先,XAML 不支持 #if def
。因此,您不能使用编译时符号来控制哪些 XAML 代码最终进入哪个项目。其次,命名空间不同。WPF 使用 System.Windows.Window
,而 Silverlight 使用 System.Windows.Controls.UserControl
。但即使您成功克服了 namespace
问题,WPF4 中也有一堆 Silverlight 3 中没有的功能(请记住,我们选择 SL3 是为了方便迁移到 Windows Phone)。因此,我们最终重写了大部分 Silverlight 应用程序。话虽如此,您仍然可以在编写 Silverlight XAML 时充分利用您的 .NET 和 WPF 技能,使用数据绑定、日期模板等。但是,我真的希望 Shawn 关于三屏编码已到来:可移植库工具允许您使用一个二进制文件针对多个 .NET 平台的工作将有助于在不久的将来减少这种摩擦。
虽然将 WPF 解决方案转换为支持 Silverlight 3 令人痛苦,但我们有意选择了 Silverlight 3 而非 Silverlight 4,因为 Windows Phone Silverlight 运行时是版本 3。原因很简单;我们希望从 Silverlight 到 Windows Phone 的移植尽可能简单。结果正是如此,从 Silverlight 到 Windows Phone 的移植非常容易。将 Silverlight 应用程序在 Windows Phone 上运行大约花费了 3 天
。
如果你查看 FlashCards.UI.Phone
项目,你会发现大多数文件都是指向 Silverlight UI 项目的链接。当我们检查显示屏幕时,差异就很明显了。在 Windows Phone Silverlight 应用程序中,只有一种显示数据的方式——在 Windows Phone 页面内。因此,Windows Phone 和 Silverlight 解决方案在这方面有所不同。但即使在这里,Silverlight 和 Windows Phone 版本也非常相似。
例如,Windows Phone 的 LearningPage.xaml 包含一个 LearningGame
用户控件 (LearningGame.xaml)。如果您查看 Silverlight 的 LearningGame.XAML,
您会发现相同的用户控件。虽然我们不得不复制 XAML 文件并进行 一些
修改以适应较小的屏幕,但控件的核心、其行为和后台代码都非常(非常)相似。因此,即使我们最终复制了 XAML 文件,核心功能仍然相同。
学到的教训
- 遗憾的是,我们无法真正共享 XAML 代码
- 某些控件可以重用
总结
显然,没有单一的万能解决方案可以在多个平台之间共享代码。话虽如此,在进行这个项目时,我们了解到在平台的限制下仍有很大的回旋余地。
- 在 WPF/SL 解决方案中使用 MVVM 可以更容易地共享模型。您的应用程序数据模型、逻辑以及对服务器端后端的任何请求都可以而且应该共享。
- 至于您的 UI,这真的取决于您的设计的复杂性,以及您希望您的实现与平台外形因素(如手机的小屏幕)的依赖程度。然而,即使在这里,也存在一定的灵活性。
非常欢迎您下载项目源代码,其中包括一些文档。并请观看 C9 上演示 3 个客户端应用程序的短视频。一如既往,我们非常欢迎您的反馈。
<object type="application/x-silverlight-2" data="data:application/x-silverlight-2," width="512" height="288"><param name="minRuntimeVersion" value="4.0.50401.0" /><param name="source" value="http://channel9.msdn.com/scripts/Channel9.xap?v=1.5" /><param name="initParams" value="mediaurl=http://media.ch9.ms/ch9/b72d/74f823fb-b458-47a6-b024-9e8c0143b72d/FlashcardsShow_ch9.wmv,thumbnail=http://media.ch9.ms/ch9/b72d/74f823fb-b458-47a6-b024-9e8c0143b72d/FlashcardsShow_512_ch9.jpg,deliverymethod=progressivedownload,autoplay=false,entryid=74f823fbb45847a6b0249e8c0143b72d" /></object>
我要感谢来自 Sela 团队的 Arik Poznanski,他帮助推动了 Flashcards.show
的第二阶段。
在 Twitter 上关注 Windows Phone 公告:WP7DEV
在 Twitter 上关注 Yochay
开始使用 免费工具、免费培训 和 免费 Jump Start 视频课程
(文章由 Barbara Alban 编辑)
[跨帖结束]
暂时就到这里,
Arik Poznanski