Эта статья является частью серии о моем опыте портирования приложений с Windows Phone на Windows 8. Официальное руководство по портированию можно найти здесь, и не забывайте следить за блогом Building Windows 8 и блогом разработчиков приложений для Windows 8 для получения последней информации.
Эта статья будет тем, что мой коллега и друг Райан Лоудермилк любит называть «частью SEO». Райан имеет в виду, что, хотя он может и не облегчить чтение с кресла, он по-прежнему будет отвечать потребностям тех, кто ищет определенную часть информации. В этой статье рассказывается о том, как часто используемые API-интерфейсы Windows Phone и функции XAML сопоставляются (или не сопоставляются) со своими аналогами в Windows 8.
В этой статье не будет много диалогов. Я расскажу, для чего используется API, покажу версию Windows Phone и покажу версию Windows 8. Если есть какие-то важные трюки, которые я хочу отметить, я тоже перечислю их.
Пространства имен XAML
Как упоминалось в первом посте, пространства имен объявляются по-разному.
WP – xmlns:imgsch="clr-namespace:ImageSearch;assembly=…" W8 – xmlns:imgsch="using:ImageSearch"
Мы изменяем clr-namespace: for using: и нам больше не нужно указывать имя сборки. Это хорошо, потому что пространство имен разрешается в разных сборках, поэтому нам не нужно иметь несколько объявлений пространства имен, если одно и то же пространство имен используется в нескольких библиотеках.
Константы XAML
Собственные типы (string, int) находятся в другом пространстве имен:
WP – <sys:String x:Key="AppName">Foo</sys:String> W8 – <x:String x:Key="AppName">Foo</x:String>
Эти типы констант редко используются в Xaml, но они пригодятся для многоразовых строк, таких как имя приложения. Просто помните, что в Windows 8 вы используете префикс x: для этих типов.
Сенсорный ввод
Windows 8 имеет единую систему ввода и больше не поддерживает специфичные для мыши события:
WP – MouseLeftButtonUp="eventhandler" W8 – PointerReleased="eventhandler"
EventHandler выше будет вызываться всякий раз , когда пользователь отпускает правую кнопку мыши, поднимает палец от дисплея или удаляет перо с поверхности. Все три устройства ввода считаются «указателями», и каждый «указатель» может отслеживаться индивидуально при желании.
Еще лучше рассмотреть возможность использования нового жеста и события Item:
W8 – Tapped="eventhandler" W8 – ItemClick="eventhandler" Note: Don’t forget IsItemClickEnabled="True"
События Item, такие как ItemClick , особенно ценны, потому что вы знаете, что a) элемент был фактически нажат и b) какой это был элемент. Это намного лучше, чем пытаться использовать событие SelectionChanged или LeftMouseButtonUp и проверять свойство SelectedItem .
Изменения в обработчике событий
RoutedEventArgs по-прежнему используется для большинства событий управления, таких как нажатие кнопки. Однако RoutedEventArgs теперь находится в другом пространстве имен (и вам придется изменить его в своем коде позади):
WP – System.Windows.RoutedEventArgs W8 – Windows.UI.Xaml.RoutedEventArgs
Так как события мыши исчезли, MouseButtonEventArgs тоже. События мыши продаются для событий жестов или указателей:
WP – System.Windows.Input.MouseButtonEventArgs W8 – Windows.UI.Xaml.Input.TappedRoutedEventArgs W8 – Windows.UI.Xaml.Input.PointerRoutedEventArgs
навигация
В Windows Phone мы переходим к Uri и передаем любые параметры как часть строки запроса. В Windows 8 мы переходим к типу страницы, и параметры можно передавать как целые объекты.
Windows Phone 7 NavigationService.Navigate(new Uri("/DetailsPage.xaml?Id=5", UriKind.Relative));
Windows 8 Frame.Navigate(typeof(DetailsPage), e.ClickedItem);
Настройки хранения — Локальные
Как Windows Phone, так и Windows 8 предоставляют способ хранения настроек приложения между запусками на одном устройстве.
Windows Phone 7 settings = IsolatedStorageSettings.ApplicationSettings; settings["exampleSetting"] = "Hello Phone";
Windows 8 settings = ApplicationData.Current.LocalSettings; container = settings.CreateContainer(“main", ApplicationDataCreateDisposition.Always); settings.Containers["main"].Values["exampleSetting"] = "Hello Windows";
Хранение настроек — роуминг
Windows 8 предоставляет способ хранения настроек приложения, которые будут синхронизироваться между устройствами пользователей. Для получения дополнительной информации см. Рекомендации по перемещению данных приложения .
Windows Phone 7 Not an option
Windows 8 settings = ApplicationData.Current.RoamingSettings; // The rest is the same as local settings
Хранение файлов — локально
Как Windows Phone, так и Windows 8 предоставляют способ хранения файлов, принадлежащих приложению.
Windows Phone 7 using (var store = IsolatedStorageFile.GetUserStoreForApplication()) { store.CreateDirectory("SampleDirectory"); rootFile = store.CreateFile("SampleFile.txt"); // Open stream rootFile.Close(); // Stream must be closed }
Windows 8 folder = ApplicationData.Current.LocalFolder; // This is a StorageFile. It is not open. file = await folder.CreateFileAsync("SampleFile.txt", CreateCollisionOption.ReplaceExisting); // Writes text and closes file in one line await FileIO.WriteTextAsync(file, "Hello World");
Хранение файлов — роуминг
Windows 8 предоставляет папку для файлов, которые будут автоматически синхронизироваться между устройствами пользователей. Для получения дополнительной информации см. Рекомендации по перемещению данных приложения .
Windows Phone 7 Not an option
Windows 8 folder = ApplicationData.Current.RoamingFolder; // The rest is the same as a local file
Хранение файлов — временное
В Windows 8 предусмотрена папка для файлов, которые будут автоматически удалены при выполнении задачи обслуживания системы.
Windows Phone 7 Not an option
Windows 8 folder = ApplicationData.Current.TemporaryFolder; // The rest is the same as a local file
Создание вторичной плитки
Как Windows Phone, так и Windows 8 предлагают вторичные плитки, но они создаются и обновляются по-разному.
Windows Phone 7 tileData = new StandardTileData { // Set tile data } ShellTile.Create(new Uri("/ItemDetail.xaml?Id=123", UriKind.Relative), tileData);
Windows 8 tile = new SecondaryTile( tileId, // Tile ID shortTitle, // Tile short name title, // Tile display name "Id=123", // Activation argument TileOptions.ShowNameOnLogo, // Tile options "ms-appx:///images/someImage.png" // Tile logo ); tile.RequestCreateAsync();
Обновление основной плитки
Важное замечание : В Windows 8 плитки создаются с использованием XML, а не классов. Microsoft создала вспомогательные классы для работы с плитками как объектами вместо XML. Эти вспомогательные классы включены в образец плиток и значков приложения . Код Windows 8 ниже использует эти вспомогательные классы.
Windows Phone 7 tile = ShellTile.ActiveTiles.First(); if (tile != null) { tileData = new StandardTileData { // Set tile data } tile.Update(tileData); }
Windows 8 wide = TileContentFactory.CreateTileWideImageAndText01(); square = TileContentFactory.CreateTileSquareImage(); wide.SquareContent = squareContent; // Set wide and square tile data wide.TextCaptionWrap.Text = "This tile uses images"; wide.Image.Src = "ms-appx:///images/redWide.png"; square.Image.Src = "ms-appx:///images/graySquare.png"; // Update TileUpdateManager.CreateTileUpdaterForApplication().Update(wide.CreateNotification());
Обновление вторичной плитки
Важное замечание : В Windows 8 плитки создаются с использованием XML, а не классов. Microsoft создала вспомогательные классы для работы с плитками как объектами вместо XML. Эти вспомогательные классы включены в образец плиток и значков приложения . Код Windows 8 ниже использует эти вспомогательные классы.
Windows Phone 7 tile = ShellTile.ActiveTiles.FirstOrDefault(<LINQ Query>); if (tile != null) { tileData = new StandardTileData { // Set tile data } tile.Update(tileData); }
Windows 8 wide = TileContentFactory.CreateTileWideImageAndText01(); square = TileContentFactory.CreateTileSquareImage(); wide.SquareContent = squareContent; // Set wide and square tile data wide.TextCaptionWrap.Text = "This tile uses images"; wide.Image.Src = "ms-appx:///images/redWide.png"; square.Image.Src = "ms-appx:///images/graySquare.png"; // Update TileUpdateManager.CreateTileUpdaterForSecondaryTile(tileId).Update(wide.CreateNotificatio
Тосты
Важное замечание : В Windows 8 тосты создаются с использованием XML, а не классов. Microsoft создала вспомогательные классы для работы с тостами как объектами вместо XML. Эти вспомогательные классы включены в пример уведомлений Toast . Код Windows 8 ниже использует эти вспомогательные классы.
Windows Phone 7 var toast = new ShellToast { Title = "Title", Content = "Toast content", NavigationUri = new Uri("ItemDetail.xaml?Id=123", UriKind.Relative) }; toast.Show();
Windows 8 toast = ToastContentFactory.CreateToastImageAndText02(); toast.TextHeading.Text = "Heading text"; toast.TextBodyWrap.Text = "Body text that wraps."; toast.Launch = “Id=123"; toast.Image.Src = "ms-appx:///images/graySquare.png"; ToastNotificationManager.CreateToastNotifier().Show(toast.CreateNotification());
Место нахождения
Windows Phone 7 watcher = new GeoCoordinateWatcher(); watcher.PositionChanged += watcher_PositionChanged; watcher.TryStart(false, TimeSpan.FromMilliseconds(2000)); // Handler private void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e) { … }
Windows 8 locator = new Geolocator(); locator.PositionChanged += locator_PositionChanged; // Handler private void locator_PositionChanged(Geolocator sender, PositionChangedEventArgs e) { … }
акселерометр
Windows Phone 7 accelerometer = new Accelerometer(); accelerometer.ReadingChanged += ReadingChanged; // Handler private void ReadingChanged(object sender, AccelerometerReadingEventArgs e) { … }
Windows 8 accelerometer = Accelerometer.GetDefault(); if (accelerometer != null) { accelerometer.ReadingChanged += ReadingChanged; } // Handler private void ReadingChanged(object sender, AccelerometerReadingChangedEventArgs e) { … }
Открыть фото
Windows Phone 7 chooser = new PhotoChooserTask(); chooser.Completed += chooser_Completed; void chooser_Completed(object sender, PhotoResult e) { if (e.TaskResult == TaskResult.OK) { BitmapImage bmp = new BitmapImage(); bmp.SetSource(e.ChosenPhoto); } }
Windows 8 var picker = new FileOpenPicker(); picker.ViewMode = PickerViewMode.Thumbnail; picker.SuggestedStartLocation = PickerLocationId.PicturesLibrary; picker.FileTypeFilter.Add(".jpg"); var file = await picker.PickSingleFileAsync(); if (file != null) { … }
Захватить фото
Windows Phone 7 chooser = new CameraCaptureTask (); chooser.Completed += chooser_Completed; void chooser_Completed(object sender, PhotoResult e) { if (e.TaskResult == TaskResult.OK) { BitmapImage bmp = new BitmapImage(); bmp.SetSource(e.ChosenPhoto); } }
Windows 8 var camera = new CameraCaptureUI(); var file = await camera.CaptureFileAsync(CameraCaptureUIMode.Photo); if (file != null) { … }
Захват видео — интерфейс системы
В Windows Phone 7 отсутствует системный пользовательский интерфейс для захвата видео (хотя пользовательский интерфейс может быть создан). В Windows 8 системный интерфейс может использоваться для захвата файлов MP4 и WMV.
Windows Phone 7 Not an option
Windows 8 CameraCaptureUI camera = new CameraCaptureUI(); camera.VideoSettings.Format = CameraCaptureUIVideoFormat.Mp4; StorageFile file = await camera.CaptureFileAsync(CameraCaptureUIMode.Video); if (file != null) { … }
Захват видео — пользовательский интерфейс
Пользовательский захват видео на обеих платформах включает в себя размещение на экране элемента, который будет отображать предварительный просмотр видео, создание устройства захвата, подключение визуального элемента к устройству захвата и захват видео в целевой файл.
Windows Phone 7 videoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice(); captureSource = new CaptureSource(); fileSink = new FileSink(); fileSink.IsolatedStorageFileName = "CameraMovie.mp4"; fileSink.CaptureSource = captureSource; videoBrush.SetSource(captureSource); viewfinderRectangle.Fill = videoBrush; captureSource.Start();
Windows 8 mediaCapture = new MediaCapture(); await mediaCapture.InitializeAsync(); previewElement.Source = mediaCapture; storageFile = await KnownFolders.VideosLibrary.CreateFileAsync("CameraMovie.mp4"); profile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto); await mediaCapture.StartRecordToStorageFileAsync(profile, storageFile);