Статьи

Запрос карты Windows Phone 8.1 при наличии дочерних объектов над ней

Вместе с Windows Phone 8.1 SDK появился (еще раз) улучшенный Map Control. Это принесло, среди прочего, MapIcon. В прежние дни карта могла рисовать только линии и полигоны изначально — когда вам приходилось рисовать значки, вы должны были добавлять дочерние объекты к самой карте, которые были нарисованы потоком пользовательского интерфейса, а не картой. Это медленнее и съедает больше ресурсов.

образНовая карта все еще предлагает такую ​​возможность. И иногда нам это тоже нужно по нескольким причинам. Прежде всего, MapIcon может отображать только изображение и дополнительную метку. Во-вторых, MapIcon нарисованы на карте с использованием «наилучшего усилия», что означает, что перекрывающиеся значки вообще не отображаются и, что еще хуже, если вы запрашиваете карту, используя метод FindMapElementsAtOffset , они также не обнаруживаются.

Поэтому в некоторых случаях нам просто нужно прибегнуть к рисованию элементов XAML, добавив в коллекцию Children карты — параметр, который, к счастью, был значительно улучшен, поскольку теперь мы, например, можем связывать эти элементы с помощью MapItemsControl, как объяснено моим умный парень MVP Шон Кендрот . До 8.1 нам для этого требовался инструментарий Windows Phone.

Но я заметил кое-что очень странное. Меня научили использовать событие MapTapped для захвата местоположения, где пользователь нажал, так как событие Tapped ловится самой картой. Это никогда не срабатывает. Поэтому я использовал MapTapped, а затем FindMapElementsAtOffset для запроса карты;

Но, к моему ужасу, я также обнаружил, что событие MapTapped не срабатывает, когда вы нажимаете на место, где отображается дочерний объект. Ergo — если вы нажмете на крестик, где отображается логотип Windows Phone, ничего не произойдет. Так как же мне узнать, что там внизу?

После некоторого разгрома я наткнулся на ответ — если вы нажмете на дочерний элемент, который находится на карте — не MapTapped, а событие Tapped срабатывает. «Событие, которое никогда не срабатывает» приходит на помощь. Кроме того, резьбовое событие на ребенке объект сам стреляет. Поэтому я создал следующий метод для запроса карты:

private void QueryMap(Point offset)
{
  foreach (var obj in MyMap.FindMapElementsAtOffset(offset))
  {
    Debug.WriteLine(obj.GetType());
  };
}

Обычный метод для ловушки MapTapped:

private void MyMap_OnMapTapped(MapControl sender, MapInputEventArgs args)
{
  Debug.WriteLine("MyMap.MapTapped occurred");
  QueryMap(args.Position);
}

И метод для перехвата Tapped, когда это происходит, и он также направляется к методу QueryMap, с небольшой помощью из метода события GetPosition:

private void MyMap_OnTapped(object sender, TappedRoutedEventArgs e)
{
  Debug.WriteLine("MayMap.Tapped occurred");
  QueryMap(e.GetPosition(MyMap));
}

И поскольку события никогда не начинаются одновременно, вы увидите, что карта обнаруживает одну PolyLine, когда вы нажимаете на линию рядом с символом, но на линии, и она заполняет поиск двух линий (пересечение обеих), когда вы нажимаете на символ, а не двойной удар от обоих событий.

Присоединив к постучали случае детского объекта можно также обнаружить , если символ сам по себе является постучал:

var childObj = new Image { 
  Source = new BitmapImage(new Uri("ms-appx:///Assets/wplogo.png")) };
MapControl.SetNormalizedAnchorPoint(childObj, new Point(0.5, 0.5));
MapControl.SetLocation(childObj, p5);
MyMap.Children.Add(childObj);
childObj.Tapped += ChildObj_Tapped;



void ChildObj_Tapped(object sender, TappedRoutedEventArgs e)
{
  Debug.WriteLine("ChildObj.Tapped occurred");
}

И, таким образом, мы можем найти все на карте, если вы приложите правильные методы к нужным событиям. Комбинация MapTapped / Tapped карты является странной, но как только вы знаете, как это сделать — несколько дополнительных строк кода делают все это.

Демо-приложение, демонстрирующее всю концепцию, можно найти здесь. Единственное, что он делает, это записывает что-то на консоль отладки, когда вы что-то делаете, поэтому обратите внимание, что там происходит 😉