Пример переноса с Windows Phone Silverlight на UWP: Bookstore1Windows Phone Silverlight to UWP case study: Bookstore1

В этом разделе представлен практический пример переноса очень простого приложения Windows Phone Silverlight в приложение UWP для Windows 10.This topic presents a case study of porting a very simple Windows Phone Silverlight app to a Windows 10 Universal Windows Platform (UWP) app. На Windows 10 можно создавать единый пакет приложения, который покупатели могут установить на широкий спектр устройств. Именно этим мы и займемся в этом примере.With Windows 10, you can create a single app package that your customers can install onto a wide range of devices, and that's what we'll do in this case study. См. раздел Руководство по приложениям UWP.See Guide to UWP apps.

Приложение, которое мы будем портировать, состоит из элемента ListBox, привязанного к модели представления.The app we'll port consists of a ListBox bound to a view model. Модель представления содержит список книг, в котором отображается заголовок, имя автора и обложка книги.The view model has a list of books that shows title, author, and book cover. У изображений обложки книги Действие при сборке установлено на Содержимое, а Копировать в выходной каталог установлено на Не копировать.The book cover images have Build Action set to Content and Copy to Output Directory set to Do not copy.

Предыдущая тема в этом разделе описывает различия между платформами. Это описание содержит подробные сведения и руководство по переносу различных элементов приложения из разметки XAML через привязку к модели представления и далее к доступу к данным.The previous topics in this section describe the differences between the platforms, and they give details and guidance on the porting process for various aspects of an app from XAML markup, through binding to a view model, down to accessing data. Цель этого практического примера — дополнить это руководство, показывая его в действии на реальном примере.A case study aims to complement that guidance by showing it in action in a real example. Предполагается, что вы ознакомились с этим руководством, которое в данных примерах не повторяется.The case studies assume you've read the guidance, which they do not repeat.

Примечание    . При открытии Bookstore1Universal _ 10 в Visual Studio, если отображается сообщение "требуется обновление Visual Studio", выполните действия по выбору версии целевой платформы в TargetPlatformVersion.Note   When opening Bookstore1Universal_10 in Visual Studio, if you see the message "Visual Studio update required", then follow the steps for selecting a Target Platform Versioning in TargetPlatformVersion.

Файлы для загрузкиDownloads

Скачать приложение Bookstore1WPSL8 для Windows Phone Silverlight.Download the Bookstore1WPSL8 Windows Phone Silverlight app.

Скачайте приложение Bookstore1Universal _ 10 Windows 10.Download the Bookstore1Universal_10 Windows 10 app.

Приложение Windows Phone SilverlightThe Windows Phone Silverlight app

Вот как Bookstore1WPSL8, приложение, которое мы собираемся переносить, выглядит.Here’s what Bookstore1WPSL8—the app that we're going to port—looks like. Это просто список книг с вертикальной прокруткой под заголовком имени и названия страницы приложения.It's just a vertically-scrolling list box of books beneath the heading of the app's name and page title.

как выглядит bookstore1wpsl8

Перенос в проект Windows 10Porting to a Windows 10 project

Создание нового проекта в Visual Studio, копирование в него файлов Bookstore1WPSL8 и подключение скопированных файлов к новому проекту не займут много времени.It's a very quick task to create a new project in Visual Studio, copy files over to it from Bookstore1WPSL8, and include the copied files in the new project. Начните с создания нового проекта пустого приложения (Windows Universal).Start by creating a new Blank Application (Windows Universal) project. Назовите его Bookstore1Universal _ 10.Name it Bookstore1Universal_10. Это файлы для копирования из Bookstore1WPSL8 в Bookstore1Universal _ 10.These are the files to copy over from Bookstore1WPSL8 to Bookstore1Universal_10.

  • Скопируйте папку, содержащую PNG-файлы с изображением книги (папка активна \ \ коверимажес).Copy the folder containing the book cover image PNG files (the folder is \Assets\CoverImages). После копирования убедитесь, что в Обозревателе решений включена функция Показать все файлы.After copying the folder, in Solution Explorer, make sure Show All Files is toggled on. Щелкните правой кнопкой мыши на скопированной папке и выберите Включить в проект.Right-click the folder that you copied and click Include In Project. Под выполнением этой команды мы и понимаем включение файлов или папок в проект.That command is what we mean by "including" files or folders in a project. Каждый раз, копируя файл или папку, нажимайте Обновить в Обозревателе решений, а затем включайте этот файл или папку в проект.Each time you copy a file or folder, click Refresh in Solution Explorer and then include the file or folder in the project. Для тех файлов, которые вы заменяете в конечном местоположении, выполнять эту операцию не нужно.There's no need to do this for files that you're replacing in the destination.
  • Скопируйте папку, содержащую исходный файл модели представления (папка — \ ViewModel).Copy the folder containing the view model source file (the folder is \ViewModel).
  • Скопируйте файл MainPage.xaml и замените на него файл в конечной папке.Copy MainPage.xaml and replace the file in the destination.

Мы можем сохранить App.xaml и App.xaml.cs, которые Visual Studio создает для нас в проекте Window 10.We can keep the App.xaml, and App.xaml.cs that Visual Studio generated for us in the Windows 10 project.

Измените только что скопированный исходный код и файлы разметки и измените все ссылки на пространство имен Bookstore1WPSL8 на Bookstore1Universal _ 10.Edit the source code and markup files that you just copied and change any references to the Bookstore1WPSL8 namespace to Bookstore1Universal_10. Эту операцию можно быстро выполнить при помощи функции Заменить в файлах.A quick way to do that is to use the Replace In Files feature. В императивном коде в исходном файле модели представления необходимо сделать следующие изменения для переноса.In the imperative code in the view model source file, these porting changes are needed:

  • Измените System.ComponentModel.DesignerProperties на DesignMode, а затем примените к нему команду Разрешить.Change System.ComponentModel.DesignerProperties to DesignMode and then use the Resolve command on it. Удалите свойство IsInDesignTool и используйте функцию IntelliSense, чтобы добавить правильное имя свойства: DesignModeEnabled.Delete the IsInDesignTool property and use IntelliSense to add the correct property name: DesignModeEnabled.
  • Примените команду Разрешить к ImageSource.Use the Resolve command on ImageSource.
  • Примените команду Разрешить к BitmapImage.Use the Resolve command on BitmapImage.
  • Удалите использование System.Windows.Media; и using System.Windows.Media.Imaging;.Delete using System.Windows.Media; and using System.Windows.Media.Imaging;.
  • Измените значение, возвращаемое свойством Bookstore1Universal _ 10. Буксторевиевмодел. AppName , с "BOOKSTORE1WPSL8" на "Bookstore1Universal".Change the value returned by the Bookstore1Universal_10.BookstoreViewModel.AppName property from "BOOKSTORE1WPSL8" to "BOOKSTORE1UNIVERSAL".

В файле MainPage.xaml необходимо сделать следующие изменения для переноса.In MainPage.xaml, these porting changes are needed:

  • Измените phone:PhoneApplicationPage на Page (не забудьте вхождения в синтаксисе элементов свойства).Change phone:PhoneApplicationPage to Page (don't forget the occurrences in property element syntax).
  • Удалите объявления префикса пространства имен phone и shell.Delete the phone and shell namespace prefix declarations.
  • Измените "clr-namespace" на "using" в остальных объявлениях префикса пространства имен.Change "clr-namespace" to "using" in the remaining namespace prefix declaration.

Мы можем очень быстро исправить ошибки компиляции разметки, если хотим как можно быстрее увидеть результаты, даже если это означает временное удаление разметки.We can choose to correct markup compilation errors very cheaply if we want to see results soonest, even if that means temporarily removing markup. Однако давайте продолжать записывать долги, которые мы накапливаем, поступая таким образом.But, let's keep a record of the debt we accrue by doing so. Вот, что получается в этом примере.Here it is in this case.

  1. В корневом элементе Page в MainPage.xaml удалите SupportedOrientations="Portrait".In the root Page element in MainPage.xaml, delete SupportedOrientations="Portrait".
  2. В корневом элементе Page в MainPage.xaml удалите Orientation="Portrait".In the root Page element in MainPage.xaml, delete Orientation="Portrait".
  3. В корневом элементе Page в MainPage.xaml удалите shell:SystemTray.IsVisible="True".In the root Page element in MainPage.xaml, delete shell:SystemTray.IsVisible="True".
  4. В шаблоне данных BookTemplate удалите ссылки на PhoneTextExtraLargeStyle и стили PhoneTextSubtleStyleTextBlock.In the BookTemplate data template, delete the references to the PhoneTextExtraLargeStyle and PhoneTextSubtleStyleTextBlock styles.
  5. В TitlePanelStackPanel удалите ссылки на PhoneTextNormalStyle и стили PhoneTextTitle1StyleTextBlock.In the TitlePanelStackPanel, delete the references to the PhoneTextNormalStyle and PhoneTextTitle1StyleTextBlock styles.

Давайте для начала поработаем с пользовательским интерфейсом для семейства мобильных устройств, а затем мы сможем рассмотреть другие форм-факторы.Let's work on the UI for the mobile device family first, and we can consider other form factors after that. Теперь вы можете выполнить сборку и запустить приложение.You can build and run the app now. Вот как это выглядит на мобильном эмуляторе.Here's how it looks on the mobile emulator.

приложение uwp на мобильном устройстве с начальными изменениями исходного кода

Представление и модель представления правильно работают друг с другом, а элемент ListBox выполняет свои функции.The view and the view model are working together correctly, and the ListBox is functioning. В основном нам просто нужно исправить оформление и заставить изображения отображаться.We mostly just need to fix the styling and get the images to show up.

Выплачивание долгов и некоторый начальный стильPaying off the debt items, and some initial styling

По умолчанию все ориентации поддерживаются.By default, all orientations are supported. Приложение Windows Phone Silverlight явным образом ограничивается только книжной ориентацией, поэтому долгие позиции # 1 и # 2 оплачиваются путем перехода в манифест пакета приложения в новом проекте и прохождения книжной ориентации под поддерживаемыми ориентациями.The Windows Phone Silverlight app explicitly constrains itself to portrait-only, though, so debt items #1 and #2 are paid off by going into the app package manifest in the new project and checking Portrait under Supported orientations.

Для этого приложения элемент # 3 не задолг, так как строка состояния (ранее называлась областью уведомлений) отображается по умолчанию.For this app, item #3 is not a debt since the status bar (formerly called the system tray) is shown by default. Для элементов # 4 и # 5 необходимо найти четыре стиля TEXTBLOCK универсальная платформа Windows (UWP), которые соответствуют используемым стилям Windows Phone Silverlight.For items #4 and #5, we need to find four Universal Windows Platform (UWP) TextBlock styles that correspond to the Windows Phone Silverlight styles that we were using. Можно запустить приложение Windows Phone Silverlight в эмуляторе и сравнить его непосредственно с иллюстрацией в разделе Текст.You can run the Windows Phone Silverlight app in the emulator and compare it side-by-side with the illustration in the Text section. По результатам этого обзора и просмотра свойств системных стилей Windows Phone Silverlight мы сможем сделать эту таблицу.From doing that, and from looking at the properties of the Windows Phone Silverlight system styles, we can make this table.

| Ключ стиля Windows Phone SilverlightWindows Phone Silverlight style key | Ключ стилей UWPUWP style key | |-------------------------------------|------------------------| | PhoneTextExtraLargeStylePhoneTextExtraLargeStyle | TitleTextBlockStyleTitleTextBlockStyle | | PhoneTextSubtleStylePhoneTextSubtleStyle | SubtitleTextBlockStyleSubtitleTextBlockStyle | | PhoneTextNormalStylePhoneTextNormalStyle | CaptionTextBlockStyleCaptionTextBlockStyle | | PhoneTextTitle1StylePhoneTextTitle1Style | HeaderTextBlockStyleHeaderTextBlockStyle |   Чтобы установить эти стили, можно просто ввести их в редактор разметки или использовать средства XAML в Visual Studio и установить их не введя ни единого знака.To set those styles, you can just type them into the markup editor or you can use the Visual Studio XAML Tools and set them without typing a thing. Для этого щелкните правой кнопкой мыши TextBlock, затем щелкните Изменить стиль > Применить ресурс.To do that, you right-click a TextBlock and click Edit Style > Apply Resource. Чтобы сделать это с TextBlock в шаблоне элементов, щелкните правой кнопкой мыши ListBox и выберите Изменить дополнительные шаблоны > Изменить созданные элементы (ItemTemplate).To do that with the TextBlocks in the item template, right click the ListBox and click Edit Additional Templates > Edit Generated Items (ItemTemplate).

За элементами присутствует на 80% непрозрачный белый фон, так как стиль по умолчанию элемента управления ListBox устанавливает фон для системного ресурса ListBoxBackgroundThemeBrush.There is an 80% opaque white background behind the items, because the default style of the ListBox control sets its background to the ListBoxBackgroundThemeBrush system resource. Установите для параметра Background="Transparent" значение ListBox, чтобы очистить этот фон.Set Background="Transparent" on the ListBox to clear that background. Чтобы выровнять TextBlock по левому краю в шаблоне элементов, отредактируйте его еще раз выше описанным способом и установите для Margin значение "9.6,0" на обоих TextBlock.To left-align the TextBlocks in the item template, edit it again the same way as described above and set a Margin of "9.6,0" on both TextBlocks.

После этого из-за изменений, связанных с пикселями представления необходимо идти дальше и умножить все фиксированные измерения размеров, которые мы еще не изменили (поля, ширина, высота и т. д.) на 0,8.After that is done, because of changes related to view pixels, we need to go through and multiply any fixed size dimension that we haven’t yet changed (margins, width, height, etc) by 0.8. Например, изображения должны измениться с 70x70 пикселей на 56x56 пикселей.So, for example, the images should change from 70x70px to 56x56px.

Однако давайте сначала заставим эти изображения отрисовываться, прежде чем покажем результаты оформления.But, let’s get those images to render before we show the results of our styling.

Привязка изображения к модели представленияBinding an Image to a view model

В Bookstore1WPSL8 мы сделали это:In Bookstore1WPSL8, we did this:

    // this.BookCoverImagePath contains a path of the form "/Assets/CoverImages/one.png".
    return new BitmapImage(new Uri(this.CoverImagePath, UriKind.Relative));

В Bookstore1Universal мы используем ms-appx Схема URI.In Bookstore1Universal, we use the ms-appx URI scheme. Чтобы сохранить остальную часть кода такой же, можно использовать другую перегрузку конструктора System.Uri, чтобы поместить схему URI ms-appx в базовый URI и добавить в него оставшуюся часть пути.So that we can keep the rest of our code the same, we can use a different overload of the System.Uri constructor to put the ms-appx URI scheme in a base URI and append the rest of the path onto that. Пример:Like this:

    // this.BookCoverImagePath contains a path of the form "/Assets/CoverImages/one.png".
    return new BitmapImage(new Uri(new Uri("ms-appx://"), this.CoverImagePath));

Универсальное оформлениеUniversal styling

Теперь необходимо выполнить окончательные настройки стиля и убедиться, что приложение выглядит хорошо на настольных (и других), а также мобильных форм-факторах.Now, we just need to make some final styling tweaks and confirm that the app looks good on desktop (and other) form factors as well as mobile. Порядок действий описан ниже.The steps are below. Вы можете использовать ссылки в верхней части данного раздела, чтобы загрузить проекты и сравнить результаты всех изменений на данном этапе и в конце примера.And you can use the links at the top of this topic to download the projects and see the results of all the changes between here and the end of the case study.

  • Чтобы сократить расстояние между элементами, найдите шаблон данных BookTemplate в файле MainPage.xaml и удалите атрибут Margin из корневого элемента Grid.To tighten up the spacing between items, find the BookTemplate data template in MainPage.xaml and delete the Margin attribute from the root Grid.
  • Если вы хотите предоставить заголовку страницы несколько больше места, можно выполнить сброс нижнего поля -5.6 до 0 в заголовке страницы TextBlock.If you want to give the page title a little more breathing room, you can reset the bottom margin of -5.6 to 0 on the page title TextBlock.
  • Теперь нам необходимо задать корректное значение по умолчанию для фона LayoutRoot, чтобы приложение выглядело соответствующим образом при запуске на всех устройствах вне зависимости от используемой темы.Now, we need to set LayoutRoot's Background to the correct default value so that the app looks appropriate when running on all devices no matter what the theme is. Измените его с "Transparent" на "{ThemeResource ApplicationPageBackgroundThemeBrush}".Change it from "Transparent" to "{ThemeResource ApplicationPageBackgroundThemeBrush}".

С более сложным приложением это была бы точка, в которой мы бы использовали руководство в разделе Перенос для форм-фактора и взаимодействия с пользователем и действительно оптимально использовали бы конструктивные параметры форм-фактора каждого из многих устройств, на которых можно запускать приложение.With a more sophisticated app, this would be the point at which we'd use the guidance in Porting for form factor and user experience and really make optimal use of the form factor of each of the many devices the app can now run on. Но для этого простого приложения можно остановить здесь и увидеть, как выглядит приложение после этой последней последовательности операций по изменению стилей.But, for this simple app, we can stop here and see how the app looks after that last sequence of styling operations. В действительности оно выглядит одинаково на мобильных и настольных устройствах, хотя пространство не используется наилучшим образом на широких форм-факторах (но мы исследуем, как это сделать, в дальнейшем примере).It actually looks the same on mobile and desktop devices, although it's not making best use of space on wide form factors (but we'll investigate how to do that in a later case study).

Способы управления темой приложения описаны в разделе Изменения тем .See Theme changes to see how to control the theme of your app.

перенесенное приложение для windows 10

Перенесенное приложение для Windows 10, запущенное на мобильном устройствеThe ported Windows 10 app running on a Mobile device

Дополнительная настройка списка для мобильных устройствAn optional adjustment to the list box for Mobile devices

При запуске на мобильном устройстве у списка по умолчанию светлый фон при использовании обеих тем.When the app is running on a Mobile device, the background of a list box is light by default in both themes. Возможно, это стиль, который вы предпочитаете. Если это так, ничего больше делать не надо.That may be the style that you prefer and, if so, then there's nothing more to do. Тем не менее элементы управления спроектированы таким образом, что вы можете настроить их внешний вид, не изменяя поведения.But, controls are designed so that you can customize their look while leaving their behavior unaffected. Поэтому если вы хотите, чтобы при использовании темной темы список был темного цвета, то есть так, как это было в оригинальном приложении, тогда следуйте этим инструкциям в разделе "Дополнительная настройка".So, if you want the list box to be dark in the dark theme—the way the original app looked—then follow these instructions under "An optional adjustment".

ЗаключениеConclusion

В этом примере показан процесс переноса очень простого приложения, вероятно, нереально простого.This case study showed the process of porting a very simple app—arguably an unrealistically simple one. Например, список элементов управления можно использовать для выбора или задания контекста для навигации; приложение переходит на страницу с дополнительной информацией об элементе, которого коснулся пользователь.For instance, list controls can be used for selection or for establishing a context for navigation; the app navigates to a page with more details about the item that was tapped. Данное приложение не выполняет никаких действий с выбором пользователя и не поддерживает ни навигацию.This particular app does nothing with the user's selection, and it has no navigation. Но даже в этом случае данный пример помог вам познакомиться с процессом портирования и продемонстрировал важные методики, которые вы можете использовать с реальными приложениями UWP.Even so, the case study served to break the ice, to introduce the porting process, and to demonstrate important techniques that you can use in real UWP apps.

Следующий пример — Bookstore2, где мы рассмотрим доступ к сгруппированным данным и их и отображение.The next case study is Bookstore2, in which we look at accessing and displaying grouped data.