Windows 运行时 8.x 到 UWP 案例研究:Bookstore2
此案例研究基于 Bookstore1 中提供的信息,从一个通用 8.1 应用开始,该应用在 SemanticZoom 控件中显示分组数据。 在视图模型中,类 Author 的每个实例都表示该作者编写的书籍组,在 SemanticZoom 中,可以查看按作者分组的书籍列表,也可以缩小以查看作者的跳转列表。 与在书籍列表中上下滚动相比,跳转列表提供了更快速的浏览方式。 我们逐步讲解将应用移植到 Windows 10 通用 Windows 平台 (UWP) 应用的步骤。
注意:在 Visual Studio 中打开 Bookstore2Universal_10 时,如果你看到消息“需要 Visual Studio 更新”,则按照 TargetPlatformVersion 中的步骤进行操作。
下载
下载 Bookstore2Universal_10 Windows 10 应用。
通用 8.1 应用
Bookstore2_81(我们将移植的应用)的外观如下。 它是水平滚动(在Windows Phone上垂直滚动)SemanticZoom,显示按作者分组的书籍。 你可以缩小到跳转列表,并从那里导航回任何组。 此应用有两个主要部分:提供分组数据源的视图模型,以及绑定到该视图模型的用户界面。 正如我们所看到的,这两个部分都可以轻松地从 WinRT 8.1 技术移植到 Windows 10。
Windows 上的Bookstore2_81,放大视图
Windows 上的 Bookstore2_81,缩小视图
Windows Phone 上的 Bookstore2_81,放大视图
Windows Phone 上的Bookstore2_81,缩小视图
移植到 Windows 10 项目
Bookstore2_81 解决方案是一个 8.1 通用应用项目。 Bookstore2_81.Windows 项目为 Windows 8.1 生成应用包,Bookstore2_81.WindowsPhone 项目为 Windows Phone 8.1 生成应用包。 Bookstore2_81.Shared 是包含经常由其他两个项目同时使用的源代码、标记文件以及其他资源的项目。
与前面的案例研究一样,我们将采用的选项( 如果你有通用 8.1 应用)将共享项目的内容移植到面向通用设备系列的 Windows 10。
首先创建新的空白应用程序(Windows 通用)项目。 将其命名为 Bookstore2Universal_10。 这些是要从 Bookstore2_81 复制到 Bookstore2Universal_10 的文件。
从共享项目
- 复制包含书籍封面图像 PNG 文件的文件夹(该文件夹是 \Assets\CoverImages)。 复制文件夹后,在解决方案资源管理器中,确保打开“显示所有文件”。 右键单击你复制的文件夹,然后单击“包括在项目中”。 此命令是指在项目中“包括”文件或文件夹。 每次你复制文件或文件夹、每个副本时,请在“解决方案资源管理器”中单击“刷新”,然后将文件或文件夹包括在项目中。 对于目标中要替换的文件,无需执行此操作。
- 复制包含视图模型源文件的文件夹(该文件夹是 \ViewModel)。
- 复制 MainPage.xaml 并替换目标中的文件。
从 Windows 项目
- 复制 BookstoreStyles.xaml。 我们将使用此密钥作为良好的起点,因为此文件中的所有资源密钥都将在 Windows 10 应用中解析;等效的 WindowsPhone 文件中的一些内容不会。
- 复制 SeZoUC.xaml 和SeZoUC.xaml.cs。 我们将从此视图的 Windows 版本开始,该视图适用于宽窗口,然后稍后我们将使其适应较小的窗口,因此,较小的设备。
编辑你刚刚复制的源代码和标记文件,并将对 Bookstore2_81 命名空间的任何引用都更改为 Bookstore2Universal_10。 执行此操作的快速方法是使用“在文件中替换”功能。 视图模型中不需要代码更改,也不需要任何其他命令性代码。 但为了更易于查看应用正在运行哪个版本的应用,请将 Bookstore2Universal_10.BookstoreViewModel.AppName 属性返回的值从“Bookstore2_81”更改为“BOOKSTORE2UNIVERSAL_10”。
现在,可以生成并运行。 下面是新 UWP 应用在尚未将其移植到 Windows 10 后的外观。
在桌面设备上运行的初始源代码更改的 Windows 10 应用,放大视图
在桌面设备上运行的初始源代码更改的 Windows 10 应用,缩小视图
视图模型和放大和缩小视图可以正确协同工作,尽管存在一些难以看到的问题。 一个问题是 SemanticZoom 不会滚动。 这是因为,在 Windows 10 中,GridView 的默认样式会导致垂直布局(Windows 10 设计指南建议我们在新的和移植的应用中以这种方式使用它)。 但是我们从 Bookstore2_81 项目(针对 8.1 应用设计)复制的自定义项面板模板中的水平滚动设置与 Windows 10 默认样式中的垂直滚动设置有冲突,应用该默认样式是移植到 Windows 10 应用所产生的后果。 第二件事是,应用尚未调整其用户界面,以便在不同大小的窗口和小型设备上提供最佳体验。 第三,尚未使用正确的样式和画笔,导致大部分文本不可见(包括可以单击以缩小的组标题)。 因此,在接下来的三个部分(SemanticZoom 和 GridView 设计更改、 自适应 UI 和 通用样式设置)中,我们将解决这三个问题。
SemanticZoom 和 GridView 设计更改
SemanticZoom 更改部分介绍了 Windows 10 中对 SemanticZoom 控件的设计更改。 对于这些更改,本部分没有工作要做。
GridView/ListView 更改部分介绍了 GridView 的更改。 为了适应这些更改,我们进行了一些非常轻微的调整,如下所述。
- 在 SeZoUC.xaml 中,在设置
ZoomedInItemsPanelTemplate
Orientation="Horizontal"
和GroupPadding="0,0,0,20"
. - 在 SeZoUC.xaml 中,从缩小视图中删除
ZoomedOutItemsPanelTemplate
和删除ItemsPanel
该属性。
大功告成!
自适应 UI
更改后,SeZoUC.xaml 给我们的 UI 布局非常适合在宽窗口中运行应用(仅在具有大屏幕的设备上运行)。 当应用的窗口很窄(这发生在小型设备上,也可能发生在大型设备上),我们在Windows Phone应用商店应用中拥有的 UI 可以说是最合适的。
可以使用自适应 Visual State Manager 功能来实现此目的。 我们将设置视觉元素的属性,以便默认情况下,UI 使用我们在 Windows Phone 应用商店应用中使用的较小模板以窄状态布局。 然后,我们将检测应用窗口的宽度是否大于或等于特定大小(以有效像素单位为单位),并且为了响应,我们将更改视觉元素的属性,以便获得更大、更宽的布局。 我们将这些属性更改置于视觉状态,我们将使用自适应触发器持续监视并确定是否应用该视觉状态,具体取决于窗口的宽度(以有效像素为单位)。 在本例中,我们在窗口宽度上触发,但也可以触发窗口高度。
最小窗口宽度为 548 epx 适用于此用例,因为这是我们想要显示宽布局的最小设备的大小。 手机通常小于 548 epx,因此在像我们一样,我们会保持默认窄布局的小型设备上。 在电脑上,窗口默认将启动足够宽,以触发切换到宽状态。 在此处,你将能够拖动足够窄的窗口,以显示 250x250 大小的项目的两列。 比这要窄一点,触发器将停用,将删除宽视觉状态,默认窄布局将生效。
因此,我们需要设置哪些属性并进行更改才能实现这两个不同的布局? 有两种替代方法,每个方法都需要不同的方法。
- 我们可以在标记中放置两个 SemanticZoom 控件。 一个将是我们在 Windows 运行时 8.x 应用中所使用的标记的副本(使用其内部的 GridView 控件),并且在默认情况下处于折叠状态。 另一个是我们在 Windows Phone 应用商店应用中使用的标记的副本(在应用商店应用中使用 ListView 控件),默认情况下可见。 视觉状态将切换两 个 SemanticZoom 控件的可见性属性。 这需要很少的努力才能实现,但一般来说,这是一种高性能技术。 因此,如果你使用它,你应该分析你的应用并确保它仍然满足你的性能目标。
- 可以使用包含 ListView 控件的单个 SemanticZoom。 为了实现我们的两个布局,在宽视觉状态中,我们将更改 ListView 控件的属性,包括应用于它们的模板,以使其与 GridView 布局的方式相同。 这性能可能更好,但 GridView 和 ListView 的各种样式和模板之间以及其各种项目类型之间存在如此多的细微差异,因此这是实现的难度更高的解决方案。 此解决方案还紧密耦合到默认样式和模板的设计方式,这给了我们一个解决方案,该解决方案对于将来对默认值所做的任何更改都比较脆弱和敏感。
在本案例研究中,我们将采用第一种替代方法。 但是,如果你愿意,你可以尝试第二个,看看这是否更适合你。 下面是实现第一个替代项所要执行的步骤。
- 在新项目的标记中的 SemanticZoom 上,设置
x:Name="wideSeZo"
和Visibility="Collapsed"
。 - 返回到 the Bookstore2_81.WindowsPhone 项目并打开 SeZoUC.xaml。 将 SemanticZoom 元素标记从该文件中复制出来,并将其立即
wideSeZo
粘贴到新项目中。 设置x:Name="narrowSeZo"
刚刚粘贴的元素。 - 但
narrowSeZo
需要一些我们尚未复制的样式。 还是在 Bookstore2_81.WindowsPhone 中,从 SeZoUC.xaml 中复制两个样式(AuthorGroupHeaderContainerStyle
和ZoomedOutAuthorItemContainerStyle
),并将它们粘贴到新项目的 BookstoreStyles.xaml 中。 - 现在,新的 SeZoUC.xaml 中有两 个 SemanticZoom 元素。 将这两个 元素包装在网格中。
- 在新项目中的 BookstoreStyles.xaml 中,将单词
Wide
追加到这三个资源键(以及 SeZoUC.xaml 中的引用,但只追加到内部wideSeZo
的引用)AuthorGroupHeaderTemplate
ZoomedOutAuthorTemplate
和BookTemplate
。 - 在 Bookstore2_81.WindowsPhone 项目中,打开 BookstoreStyles.xaml。 从此文件中,复制这三个相同的资源(如上所述)、两个跳转列表项转换器以及命名空间前缀声明 Windows_UI_Xaml_Controls_Primitives,然后将它们全部粘贴到新项目的 BookstoreStyles.xaml 中。
- 最后,在新项目中的 SeZoUC.xaml 中,将相应的 Visual State Manager 标记添加到上面添加的 网格 。
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="WideState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="548"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="wideSeZo.Visibility" Value="Visible"/>
<Setter Target="narrowSeZo.Visibility" Value="Collapsed"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
...
</Grid>
通用样式
现在,让我们修复一些样式问题,包括从旧项目复制时介绍的样式问题。
- 在 MainPage.xaml 中,将'后台更改为
LayoutRoot
"{ThemeResource ApplicationPageBackgroundThemeBrush}"
. - 在 BookstoreStyles.xaml 中,将资源
TitlePanelMargin
0
的值设置为(或任何值都适合你)。 - 在 SeZoUC.xaml 中,将边距
wideSeZo
0
设置为(或任何值都适合你)。 - 在 BookstoreStyles.xaml 中,从
AuthorGroupHeaderTemplateWide
中删除 Margin 属性。 - 从
AuthorGroupHeaderTemplate
/从ZoomedOutAuthorTemplate
中删除 FontFamily 属性。 - Bookstore2_81 使用了
BookTemplateTitleTextBlockStyle
、BookTemplateAuthorTextBlockStyle
和PageTitleTextBlockStyle
资源键作为间接寻址,以便单个键在两个应用中具有不同的实现。 我们不再需要这种间接性;我们可以直接引用系统样式。 因此,请将整个应用内的引用分别替换为TitleTextBlockStyle
和CaptionTextBlockStyle
HeaderTextBlockStyle
分别替换这些引用。 可以使用 Visual Studio “在文件中替换” 功能快速准确地执行此操作。 然后,可以删除这三个未使用的资源。 - 在
AuthorGroupHeaderTemplate
TextBlock 上替换PhoneAccentBrush
SystemControlBackgroundAccentBrush
并设置Foreground="White"
,以便在移动设备系列上运行时看起来正确。 - 在
BookTemplateWide
中,将 Foreground 属性从第二个 TextBlock 复制到第一个。 - 在
ZoomedOutAuthorTemplateWide
,将引用SubheaderTextBlockStyle
(现在太大)更改为引用SubtitleTextBlockStyle
。 - 放大视图(跳转列表)不再覆盖新平台中的放大视图,因此我们可以从缩小视图
narrowSeZo
中删除Background
该属性。 - 因此,所有样式和模板都位于一个文件中,移
ZoomedInItemsPanelTemplate
出 SeZoUC.xaml 并移动到 BookstoreStyles.xaml 中。
最后一系列样式设置操作使应用看起来如下所示。
在桌面设备上运行的已移植的 Windows 10 应用,放大视图,两个大小的窗口
在桌面设备上运行的已移植的 Windows 10 应用,缩小视图,两个大小的窗口
在移动设备上运行的已移植的 Windows 10 应用,放大视图
在移动设备上运行的已移植的 Windows 10 应用,缩小视图
结束语
此案例研究涉及比上一个更雄心勃勃的用户界面。 与前面的案例研究一样,此特定视图模型根本不需要工作,我们的工作主要是为了重构用户界面。 其中一些更改是将两个项目组合成一个项目的必要结果,同时仍然支持许多外形规格(事实上,比我们以前可以多得多)。 其中一些更改与对平台所做的更改有关。
下一个案例研究是 QuizGame,我们将在其中查看访问和显示分组数据。