Основная страница нашего приложения построена с использованием элемента управления Pivot, на одной из закладок которого необходимо было разместить карту с информацией о местоположении автомобиля. Пользователям нашего приложения было решено предоставить выбор между сервисами карт от компании Микрософт и компании Яндекс.
Интеграция встроенного сервиса карт не составило никакого труда, так как элемент управления для отображения карт является частью операционной системы, и его интеграция со всеми стандартными элементами управления отработана до мелочей.
Однако с интеграцией элемента управления для отображения карт входящего в Yandex.Map MapKit от компании Яндекс возникли неожиданные сложности. Попытки манипуляции картой в горизонтальной плоскости приводили к переключению текущей закладки элемента управления Pivot.
Изучение проблемы показало, что в Windows Phone 8 были произведены оптимизации обработки жестов. В результате чего, события о манипуляциях пользователя могут перехватываться встроенными элементами управления, до передачи их в дочерние элементы управления. Перехват событий осуществляют следующие элементы управления: DrawingSurface, DrawingSurfaceBackgroundGrid, ListBox, LongListSelector, Map, Panorama, Pivot, ScrollViewer, ViewportControl, WebBrowser.
К сожалению инструментарий Yandex.Maps MapKit больше не поддерживается компанией Яндекс, а последняя доступная версия разработана для Windows Phone 7.5 в которой указанные оптимизации отсутствуют.
Оптимизации операционной системы можно отключить установив значение свойства UseOptimizedManipulationRouting элемента управления в false. Но после установки значения свойства поведение приложения не изменилось. Все дело в том, что включив обработку жестов для элемента управления, так же необходимо обработать события: ManipulationStarted, ManipulationDelta и ManipulationCompleted. Нам нет необходимости обрабатывать жесты пользователя в этих обработчиках, так как этим занимается элемент управления Map, достаточно установить флаг Handled в true уведомив остальные элементы управления, что событие уже обработано.
После описанных действий приложение начинает работать как ожидается, а именно при манипулировании картой во всех плоскостях, не происходит смены текущей закладки элемента управления Pivot.
Проведение указанных действий можно перенести на декларативный уровень, реализовав присоединяемое свойство и реализовав все выше описанное в его обработчике
Теперь можно в разметке страницы установить это свойство в true для элемента управления Map избежав написания лишнего кода.
Все выше описанное применимо к другим элементам управления, для которых имеют значение горизонтальные жесты пользователя, например, элемент управления Slider. Немного модифицировав код присоединяемого свойства можно сделать его универсальным и использовать с любым элементом управления, нуждающимся в обработке горизонтальных жестов пользователя.
Тестовый проект доступен на GitHub
Интеграция встроенного сервиса карт не составило никакого труда, так как элемент управления для отображения карт является частью операционной системы, и его интеграция со всеми стандартными элементами управления отработана до мелочей.
Однако с интеграцией элемента управления для отображения карт входящего в Yandex.Map MapKit от компании Яндекс возникли неожиданные сложности. Попытки манипуляции картой в горизонтальной плоскости приводили к переключению текущей закладки элемента управления Pivot.
Изучение проблемы показало, что в Windows Phone 8 были произведены оптимизации обработки жестов. В результате чего, события о манипуляциях пользователя могут перехватываться встроенными элементами управления, до передачи их в дочерние элементы управления. Перехват событий осуществляют следующие элементы управления: DrawingSurface, DrawingSurfaceBackgroundGrid, ListBox, LongListSelector, Map, Panorama, Pivot, ScrollViewer, ViewportControl, WebBrowser.
К сожалению инструментарий Yandex.Maps MapKit больше не поддерживается компанией Яндекс, а последняя доступная версия разработана для Windows Phone 7.5 в которой указанные оптимизации отсутствуют.
Оптимизации операционной системы можно отключить установив значение свойства UseOptimizedManipulationRouting элемента управления в false. Но после установки значения свойства поведение приложения не изменилось. Все дело в том, что включив обработку жестов для элемента управления, так же необходимо обработать события: ManipulationStarted, ManipulationDelta и ManipulationCompleted. Нам нет необходимости обрабатывать жесты пользователя в этих обработчиках, так как этим занимается элемент управления Map, достаточно установить флаг Handled в true уведомив остальные элементы управления, что событие уже обработано.
После описанных действий приложение начинает работать как ожидается, а именно при манипулировании картой во всех плоскостях, не происходит смены текущей закладки элемента управления Pivot.
Проведение указанных действий можно перенести на декларативный уровень, реализовав присоединяемое свойство и реализовав все выше описанное в его обработчике
using System.Windows;
using Yandex.Maps;
namespace YandexMapKit
{
public static class YandexMapHelper
{
public static readonly DependencyProperty FixManipulationProperty = DependencyProperty.RegisterAttached(
"FixManipulation", typeof(bool), typeof(YandexMapHelper), new PropertyMetadata(OnFixManipulationChanged));
public static void SetFixManipulation(DependencyObject element, bool value)
{
element.SetValue(FixManipulationProperty, value);
}
public static bool GetFixManipulation(DependencyObject element)
{
return (bool) element.GetValue(FixManipulationProperty);
}
private static void OnFixManipulationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var map = d as Map;
if (map == null)
{
return;
}
var fixManipulation = (bool?) e.NewValue;
if (fixManipulation == true)
{
map.UseOptimizedManipulationRouting = false;
map.ManipulationStarted += MapManipulationStarted;
map.ManipulationCompleted += MapManipulationCompleted;
map.ManipulationDelta += MapManipulationDelta;
return;
}
fixManipulation = (bool?)e.OldValue;
if (fixManipulation == true)
{
map.UseOptimizedManipulationRouting = true;
map.ManipulationStarted -= MapManipulationStarted;
map.ManipulationCompleted -= MapManipulationCompleted;
map.ManipulationDelta -= MapManipulationDelta;
}
}
private static void MapManipulationDelta(object sender, System.Windows.Input.ManipulationDeltaEventArgs e)
{
e.Handled = true;
}
private static void MapManipulationCompleted(object sender, System.Windows.Input.ManipulationCompletedEventArgs e)
{
e.Handled = true;
}
private static void MapManipulationStarted(object sender, System.Windows.Input.ManipulationStartedEventArgs e)
{
e.Handled = true;
}
}
}
Теперь можно в разметке страницы установить это свойство в true для элемента управления Map избежав написания лишнего кода.
<phone:Pivot Title="YANDEX MAPKIT TEST APP">
<phone:PivotItem Header="описание">
<StackPanel>
<RichTextBox VerticalAlignment="Top" VerticalContentAlignment="Top">
<Paragraph>
<Run Text="Приложение демонстрирует работу элемента управления Map из набора разработчика Yandex.Maps MapKit при его размещении на элемнете управления Pivot"/>
</Paragraph>
</RichTextBox>
<CheckBox x:Name="viewFixManipulation" Content="Включить исправления" VerticalAlignment="Top" />
</StackPanel>
</phone:PivotItem>
<phone:PivotItem Header="карта">
<Grid>
<yandexMaps:Map yandexMapKit:YandexMapHelper.FixManipulation="{Binding IsChecked, ElementName=viewFixManipulation}" />
</Grid>
</phone:PivotItem>
</phone:Pivot>
Все выше описанное применимо к другим элементам управления, для которых имеют значение горизонтальные жесты пользователя, например, элемент управления Slider. Немного модифицировав код присоединяемого свойства можно сделать его универсальным и использовать с любым элементом управления, нуждающимся в обработке горизонтальных жестов пользователя.
Тестовый проект доступен на GitHub