2016-06-30 2 views
1

Я использую MVVM-ориентированную вилку библиотеки GreatMaps.NET (https://greatmaps.codeplex.com/), но мой вопрос сводится к основной проблеме с использованием пользовательского Canvas в качестве моей ItemsPanel для ItemsControl. По сути, карта является ItemsControl, с MapCanvas размещения своих детей следующим образом:ArrangeOverride не вызывает детей?

protected override Size ArrangeOverride(Size arrangeSize) 
{ 
    foreach (UIElement child in Children) 
    { 
     PointLatLng position = new PointLatLng(GetTop(child), GetLeft(child)); 

     GMapControl map = Owner as GMapControl; 
     if (map != null) 
     { 
      GPoint p = map.FromLatLngToLocal(position); 
      p.Offset(-(long)(map.MapTranslateTransform.X + child.DesiredSize.Width * 0.5), -(long)(map.MapTranslateTransform.Y + child.DesiredSize.Height * 0.5)); 

      Rect rect = new Rect(p.X, p.Y, child.DesiredSize.Width, child.DesiredSize.Height); 
      child.Arrange(rect); 
     } 
    } 
    return arrangeSize; 
} 

Это работает, потому что мой ItemContainerStyle связывается с широтой и долготой в ViewModel для каждого элемента карты следующим образом (вместе с ZIndex, который я установили 99 в качестве заполнителя):

<Setter Property="Canvas.Left" Value="{Binding Longitude}" /> 
<Setter Property="Canvas.Top" Value="{Binding Latitude}" /> 
<Setter Property="Canvas.ZIndex" Value="{Binding ZIndex}" /> 

Я использую DataTemplates с DATATYPE полями для настройки получает отображается каждый элемент, и эта часть работает должным образом.

Есть элементы (такие как линии для маршрутов на карте), которые мне нужно иметь не как точки, а как последовательности подэлементов. Чтобы сделать это, я просто следил за шаблоном и сделал DataTemplate, где я использую другой MapCanvas, привязанный к тому же MapControl, что и его владелец (здесь MapOverlay - это всего лишь копия MapCanvas, которая переопределяет OnRender, чтобы нарисовать линии между его дочерними элементами):

<DataTemplate DataType="{x:Type viewModels:RouteViewModel}"> 
    <ItemsControl ItemsSource="{Binding Locations}"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <wpf:MapOverlay Name="MapOverlay" Owner="{Binding Path=., RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type wpf:GMapControl}}}"/> 
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
     <ItemsControl.ItemContainerStyle> 
      <Style> 
       <Setter Property="Canvas.Left" Value="{Binding Longitude}" /> 
       <Setter Property="Canvas.Top" Value="{Binding Latitude}" /> 
       <Setter Property="Canvas.ZIndex" Value="{Binding ZIndex}" /> 
      </Style> 
     </ItemsControl.ItemContainerStyle> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <Ellipse Fill="Blue" Stroke="Black" Width="10" Height="10"></Ellipse> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
</DataTemplate> 

чтобы привязок работать, RouteViewModel до сих пор имеет свой собственный LAT/LNG, который, кажется, только работы, когда я расположить их в начальной точке списка точек по маршруту:

public double Latitude => Locations.Select(loc => loc.Latitude).FirstOrDefault(); 
public double Longitude => Locations.Select(loc => loc.Longitude).FirstOrDefault(); 

Резюме:

  • У меня есть элемент управления GMapControl с использованием MapCanvas для элементов геопространственного положения. DataTypes используются для выбора того, какой DataTemplate используется для каждого элемента. Это работает для точечных элементов, таких как маркеры.
  • Один из DataTemplates - это ItemControl, который использует еще один вариант MapCanvas (MapOverlay) в качестве элемента ItemsPanel для рисования линий между подэлементами. Это работает при запуске, когда выполняется ArrangeOverride.
  • Панорамирование карт работает, хотя ArrangeOverride не вызывается в MapOverlay.

Проблема: в то время как мои элементы появляются изначально в правильном положении, масштабирование карты (который спровоцировав InvalidateVisual и UpdateLayout через контроль карты) не вызывает ArrangeOverride называться на вложенной MapOverlay. Это приводит к тому, что маршрут больше не позиционируется должным образом - он не масштабируется.

Любые предложения относительно того, почему недействительность аранжировки не стекается к вложенному MapOverlay и/или советам по ее устранению?

Приложение: Маршрут был помещен правильно, когда карта была первоначально позиционирована в ее первом элементе - широта/долгота маршрута в целом является отдельной проблемой, на которую я бы приветствовал идеи.

+0

Если вам интересно, я мог бы вам легко отобразить маршрут (например, круги, связанные с линиями) с помощью моего [XAML MapControl] (http://xamlmapcontrol.codeplex.com/). MVVM, конечно. – Clemens

+0

Я видел ваш проект, упомянутый - это было бы очень полезно! Спасибо! – Methalous

+0

Как вы масштабируетесь? Я бы использовал TransformGroup в RenderTransform для корня карты, которая имеет ScaleTransform и TranslateTransform, который управляет масштабированием и панорамированием. Как это было бы сделано во время прохода рендеринга, это никак не повлияет на макет. Кроме того, имеется ряд средств управления масштабированием, доступных из разных источников, которые вы могли бы использовать для управления этим аспектом, не беспокоясь о макете на карте. – Will

ответ

0

На самом деле не ответ на ваш вопрос, но он может дать вам общее представление о том, как показать маршрут, т. Е. Набор кругов, соединенных линиями.

Следующий образец использует библиотеку XAML MapControl, но может быть реализован на основе любой другой библиотеки карт, которая имеет вид MapItemsControl (например, MS Bing Maps).

Идея состоит в том, чтобы иметь набор из Location экземпляров, составляющих ваш маршрут. У вас будет MapPolyline и привяжите его свойство Locations к количеству точек маршрута. Затем положите на него MapItemsControl и привяжите его ItemsSource к той же коллекции. Обратите внимание: ItemTemplate использует элементы управления «Путь» с помощью EllipseGeometries вместо Ellipses, потому что они центрированы в месте точки, в то время как эллипсы расположены сверху/влево.

<map:MapPanel> 

    <map:MapPolyline Locations="{Binding RouteLocations}" 
        Stroke="DarkBlue" StrokeThickness="3"/> 

    <map:MapItemsControl ItemsSource="{Binding RouteLocations}"> 
     <map:MapItemsControl.ItemContainerStyle> 
      <Style TargetType="map:MapItem"> 
       <Setter Property="map:MapPanel.Location" Value="{Binding}"/> 
      </Style> 
     </map:MapItemsControl.ItemContainerStyle> 
     <map:MapItemsControl.ItemTemplate> 
      <DataTemplate> 
       <Path Fill="Red"> 
        <Path.Data> 
         <EllipseGeometry RadiusX="5" RadiusY="5"/> 
        </Path.Data> 
       </Path> 
      </DataTemplate> 
     </map:MapItemsControl.ItemTemplate> 
    </map:MapItemsControl> 

</map:MapPanel> 

Если точки маршрута не Location s можно использовать связующие конвертеры в обеих привязках для преобразования вашего маршрута типа точки на Location.

+0

Привет, Клеменс, теперь я использую ваш XAMLMapControl и считаю, что с ним легко работать. Тем не менее, у меня есть несколько маршрутов на моей карте - как я могу использовать то, что вы только что определили для каждого элемента коллекции? – Methalous

+0

Ive никогда не пробовал, но вы, вероятно, сможете разместить всю MapPanel с этого поста в ItemTemplate другого внешнего MapItemsControl. – Clemens

Смежные вопросы