Вместе с 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 карты является странной, но как только вы знаете, как это сделать — несколько дополнительных строк кода делают все это.
Демо-приложение, демонстрирующее всю концепцию, можно найти здесь. Единственное, что он делает, это записывает что-то на консоль отладки, когда вы что-то делаете, поэтому обратите внимание, что там происходит ?