Упражнение 1. Приложение Running Tracker

На этом практическом занятии мы создадим новое приложение Windows Phone с единственным представлением, которое использует новый элемент управления картой и API Maps. Приложение будет отображать маршрут пробежки пользователя, проложенный между двумя географическими точками. В первой части занятия мы добавим несколько элементов пользовательского интерфейса, которые понадобятся нам позже. При выполнении упражнений мы не будем использовать службу географического позиционирования, вместо этого мы сэмулируем информацию о местоположении с помощью жестко заданных координат.

Задание 1. Создание приложения и начальное изменение его манифеста

В данном задании мы создадим новое приложение для ОС Windows Phone 8 и подготовим его для выполнения последующих действий. С этой целью мы изменим манифест приложения таким образом, чтобы оно могло использовать элемент управления картой. Приложение Running Tracker использует элемент управления картой, который требует, чтобы в манифесте была объявлена функция ID_CAP_MAP.

  1. Откройте Visual Studio Express 2012 для Windows Phone.
  2. Создайте новое приложение Windows Phone 8 и назовите его RunningTracker.
  3. В обозревателе решений перейдите в папку Properties и найдите файл WMAppManifest.xml. Дважды щелкните этот файл и откройте конструктор манифеста.
  4. Перейдите в раздел Capabilities (Функции), найдите функцию IC_CAP_MAP и включите ее, установив флажок.

    Рис. 1.
    Раздел Capabilities в манифесте приложения

  5. Сохраните изменения. Теперь, когда манифест приложения изменен, мы перейдем к добавлению элементов пользовательского интерфейса.

Задание 2. Создание пользовательского интерфейса приложения

В данном задании мы добавим в приложение начальный пользовательский интерфейс. Running Tracker — это простое приложение с одной страницей, которую мы реализуем в файле MainPage.xaml. Мы изменим страницу, добавив на нее элемент управления картой (он займет большую часть страницы), несколько текстовых блоков, отображающих текущее состояние приложения и сообщения, а также единственную кнопку для включения и выключения основной функции приложения.

Изменение файла MainPage.xaml:

  1. Откройте файл MainPage.xaml.
  2. Найдите стопку StackPanel под названием TitlePane.
  3. В стопке измените свойство текста первого блока на Running Tracker.
<TextBlock Text="Running Tracker" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>

4. Измените свойство текста в текстовом блоке на «Let’s run!» (Побежали!):

<TextBlock Text="Let's Run!" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>

5. Мы сделали заголовок и теперь можем приступить к созданию содержимого основного представления. Найдите сетку с названием ContentPanel и задайте в ней три строки:

<Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions>

В этом фрагменте кода мы объявили, что первая строка займет столько места, сколько можно под нее выделить (в ней мы расположим элемент управления картой); во второй и третьей строках будут размещены текстовые блоки для сообщений и кнопка управления.

Примечание.

Далее мы добавим в пользовательский интерфейс дополнительные элементы управления.

6. Теперь добавим кнопку Start/Stop (Запустить/Остановить). Добавьте следующий код XAML сразу же за предыдущим (с определениями строк сетки):

<Button Grid.Row="1" Content="Start" x:Name="btnStartStop" Click="btnStartStop_Click" MinWidth="200" Height="72" VerticalAlignment="Top"/>

Этот код добавляет в представление новую кнопку. Она будет использоваться для запуска и остановки приложения; надписи Start и Stop на кнопке будут меняться в зависимости от состояния приложения из файла кода программной части (C#).

7. На следующем этапе мы добавим в представление элемент управления картой. Класс элемента управления картой принадлежит к пространству имен Microsoft.Phone.Maps.Controls, а это означает, что перед его использованием нужно объявить пространство имен XML. Найдите тег phone:PhoneApplicationPage и добавьте после других пространств следующее определение пространства имен XML:
xmlns:maps="clr-namespace:Microsoft.Phone.Maps. Controls;assembly=Microsoft.Phone.Maps"

8. Теперь объявим в коде XAML представления элемент управления картой. Перейдите к коду кнопки в файле и добавьте следующий участок кода сразу же после объявления кнопки:

<maps:Map x:Name="map" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Visibility="Collapsed"/>

Примечание.

Этот фрагмент кода добавляет в представление элемент управления картой, скрытый от пользователя. Далее мы добавим код, который сделает элемент видимым после инициализации и сбора данных о местоположении.

9. Наконец, мы добавим текстовый блок, который появится в случае, если пользователю не будет виден элемент управления картой. После кода элемента управления картой, реализованного на предыдущем этапе, добавьте следующий фрагмент кода:

<TextBlock Text="Tap the 'Start' button when ready" HorizontalAlignment="Center" VerticalAlignment="Center" x:Name="txtMessage"/>

10. Мы завершили работу с представлением, однако проект не компилируется, поскольку в файле кода программной части C# пока что не объявлены некоторые события из файла XAML. Мы сделаем это на следующем этапе.

Задание 3. Работа с API Maps и элементом управления картой в файле кода программной части

Приложение Running Tracker позволяет отслеживать местоположение пользователя во время пробежек, поездок на велосипеде или пеших походов. В этом задании мы будем использовать API Maps для прокладки маршрута между двумя географическими точками и его отображения на карте. Мы пока что не будем задействовать службу Windows Phone 8 для определения местоположения: вместо это мы будем эмулировать движение по маршруту с помощью статических координат.

Примечание.

Служба определения местоположения будет добавлена в задании 2 практического занятия.

А в этом задании мы будем программировать элемент управления картой и обратимся к классу RouteQuery (часть пространства имен Microsoft.Phone.Maps.Services), чтобы реализовать поддержку навигации.

  1. Откройте файл MainPage.xaml.cs, найдите раздел using в самом начале файла и добавьте следующий код для объявления пространства имен, которые потребуются нам далее.
using Microsoft.Phone.Maps.Controls; using Microsoft.Phone.Maps.Services; using System.Device.Location;

2. Теперь добавим в этот класс несколько констант. Перед комментарием //Constructor добавьте следующий код:

private const double SourceLatitude = 48.85815; //Eiffel Tower private const double SourceLongtitude = 2.29452; //Eiffel Tower private const double DestinationLatitude = 48.860395; //The Louvre private const double DestinationLongtitude = 2.337599; //The Louvre

3. Далее добавьте несколько членов класса сразу же после предыдущего блока кода:

RouteQuery routeQuery = new RouteQuery(); List<GeoCoordinate> waypoints = new List<GeoCoordinate>();

Константы этих координат служат для расчета расстояния и прокладки маршрута между двумя популярными туристическими объектами в Париже — Эйфелевой башней и Лувром.

Класс RouteQuery будет использоваться для расчета маршрута между двумя географическими точками и более. Результаты этого запроса позволят проложить маршрут на карте и рассчитать расстояние от начальной до конечной точки в следующем упражнении.

Чтобы рассчитать маршрут, классу RouteQuery нужен список объектов GeoCoordinate. Переменная waypoints служит для поддержки этих координат.

Наконец, класс GeoCoordinate (из пространства имен System.Device.Location) представляет собой местоположение, выраженное двумя географическими координатами — широтой и долготой.

4. Чтобы инициализировать класс RouteQuery и задать несколько свойств элемента управления картой, применим метод OnNavigatedTo. Данный метод, унаследованный из базового класса Page, вызывается автоматически — при активации страницы в кадре. После конструктора класса добавьте следующий код:

protected override void OnNavigatedTo(NavigationEventArgs e) { map.ColorMode = MapColorMode.Light; map.CartographicMode = MapCartographicMode.Road; map.LandmarksEnabled = true; map.PedestrianFeaturesEnabled = true; map.ZoomLevel = 17; routeQuery.TravelMode = TravelMode.Walking; routeQuery.QueryCompleted += rq_QueryCompleted; base.OnNavigatedTo(e); }

Примечание.

Изменять свойства элемента управления картой (такие как ColorMode, LandmarksEnabled и другие) можно непосредственно из XAML.

Первые несколько строк данного кода настраивают элемент управления картой в соответствии с требованиями нашего приложения: мы меняем цветовую схему карты и режим картографии, включаем режим пешехода и настраиваем масштаб карты. Далее инициализируем объект RouteQuery с режимом прохождения маршрута, который требуется для нашего приложения. Это режим пешехода, поскольку приложение предназначено для записи маршрутов пробежек, велопрогулок или пеших турпоходов. Функция RouteQuery требует интернет-соединения и использует асинхронные вызовы, поэтому мы подписываемся на асинхронный вызов, когда запрос успешно обработан и возвращает результат.

5. Как указано выше, для прокладки маршрута между двумя точками RouteQuery использует асинхронный метод, и нам нужно указать метод обработчика событий для завершения запроса. Сразу после предыдущего метода добавьте следующий код:

void rq_QueryCompleted(object sender, QueryCompletedEventArgs<Route> e) { if (null == e.Error) { //Recommended way to display route on map Route MyRoute = e.Result; MapRoute MyMapRoute = new MapRoute(MyRoute); map.AddRoute(MyMapRoute); } else MessageBox.Show("Error occured:\n" + e.Error.Message); }

Получив результаты запроса, мы создаем новый объект MapRoute для представления полученного маршрута, и добавляем его на карту с помощью метода AddRoute.

6. И последнее (по порядку, но не по степени важности): нам нужно добавить обработчик событий для кнопки, объявленной в задании 2. Сразу же после предыдущего блока кода добавьте следующий код:

private void btnStartStop_Click (object sender, RoutedEventArgs e) { map.Center = new GeoCoordinate(SourceLatitude, SourceLongtitude); map.Visibility = System.Windows.Visibility.Visible; waypoints = new List<GeoCoordinate> { new GeoCoordinate(SourceLatitude, SourceLongtitude), new GeoCoordinate(DestinationLatitude, DestinationLongtitude) }; if (!routeQuery.IsBusy) { routeQuery.Waypoints = waypoints; routeQuery.QueryAsync(); } }

Данный метод обрабатывает событие, которое возникает, когда пользователь касается кнопки Start/Stop. В ходе этого упражнения мы используем эту кнопку только в режиме Start.

Вначале метод устанавливает центр карты в координату начальной точки и отображает в представлении элемент управления картой, меняя возможность его обзора. Элемент управления картой центруется по указанным координатам.

Чтобы рассчитать маршрут с помощью класса RouteQuery, нам нужно предоставить список географических координат. Переменная wayPoints инициализируется с помощью жестко заданных координат начальной и конечной точек, объявленных как константы ранее при выполнении данного задания. Объект RouteQuery обрабатывает запрос в асинхронном режиме после того, как мы осуществили вызов метода QueryAsync. Это означает, что:

  • На выполнение операции может потребоваться значительное время (до нескольких секунд).
  • Пока ожидаются результаты запроса, пользовательский интерфейс нашего приложения не блокируется.

Иными словами, до получения результатов предыдущего запроса пользователь может еще раз коснуться кнопки Start. Нам нужно избежать вызова метода QueryAsync до того, как будут получены результаты предыдущего запроса, поэтому вышеуказанный код проверяет состояние объекта RouteQuery, чтобы убедиться, что метод не обрабатывает предыдущий запрос. Это делается путем загрузки свойства IsBusy.

Примечание.

При попытке вызова метода QueryAsync до того, как завершена обработка предыдущего запроса (если он не был отменен с помощью метода CancelAsync), выполняется исключение InvalidOperationException с сообщением: «Cannot start another query while one is running» (Нельзя отправить запрос, пока обрабатывается предыдущий).

  1. Наше приложение готово. Скомпилируйте, разверните и запустите приложение.

    Рис. 2.
    Главный экран приложения

    Нажмите кнопку Start (Запустить). Приложение рассчитает и покажет на карте маршрут от Эйфелевой башни до Лувра.

    Рис. 3.
    Карта с отображенными на ней ориентирами и маршрутом

  2. Мы выполнили первое задание. Остановите приложение и вернитесь в Visual Studio. В следующем упражнении мы добавим в приложение службу определения местоположения, чтобы отслеживать движение пользователя, а также поддержку фонового выполнения приложения.

Предыдущая | Следующая