Ich verwende einen MVVM-orientierten Fork der GreatMaps.NET-Bibliothek (https://greatmaps.codeplex.com/), aber meine Frage geht auf ein grundlegendes Problem mit einem benutzerdefinierten Canvas als ItemsPanel für ein ItemsControl. Im Wesentlichen ist die Karte ein Itemscontrol, mit einem MapCanvas seine Kinder setzen sich wie folgt:ArrangeOverride wird nicht an Kinder gerufen?
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;
}
Das funktioniert, weil mein ItemContainerStyle im Ansichtsmodell für jedes Kartenelement Breiten- und Längen bindet wie folgt (zusammen mit ZIndex, die ich haben bis 99 als Platzhalter eingestellt):
<Setter Property="Canvas.Left" Value="{Binding Longitude}" />
<Setter Property="Canvas.Top" Value="{Binding Latitude}" />
<Setter Property="Canvas.ZIndex" Value="{Binding ZIndex}" />
I Datatemplates mit Feldern des Datentyps anzupassen bin mit, wie jedes Element angezeigt wird, und dass ein Teil richtig funktioniert.
Es gibt Elemente (z. B. Linien für Routen auf der Karte), die ich nicht als Punktelemente, sondern als Folgen von Unterelementen haben muss. Dazu folgte ich einfach dem Muster und erstellte ein DataTemplate, in dem ich ein anderes MapCanvas verwendete, das an dasselbe MapControl gebunden war wie der Besitzer (MapOverlay ist nur eine Kopie von MapCanvas, die OnRender überschreibt, um Linien zwischen den untergeordneten Elementen zu zeichnen):
<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>
um die Bindungen weiter arbeitet, der RouteViewModel noch seine eigenen Lat/Lng hat, das nur zu arbeiten scheint, wenn ich sie in dem Anfangspunkt der Liste der Punkte entlang der Route positionieren:
public double Latitude => Locations.Select(loc => loc.Latitude).FirstOrDefault();
public double Longitude => Locations.Select(loc => loc.Longitude).FirstOrDefault();
In Zusammenfassung:
- Ich habe ein GMapControl ItemsControl mit einem MapCanvas, um Elemente geografisch zu positionieren. DataTypes werden verwendet, um auszuwählen, welches DataTemplate für jedes Element verwendet wird. Dies funktioniert für punktbasierte Elemente wie Marker.
- Eines der DataTemplates ist ein ItemsControl, das eine weitere MapCanvas-Variante (MapOverlay) als ItemsPanel zum Zeichnen von Linien zwischen Unterelementen verwendet. Dies funktioniert beim Start, wenn ArrangeOverride ausgeführt wird.
- Das Verschieben der Karte funktioniert, obwohl ArrangeOverride nicht in MapOverlay aufgerufen wird.
Das Problem: während meine Elemente zunächst richtig positioniert erscheinen, Zoomen der Karte (die eine InvalidateVisual und UpdateLayout über die Karte Steuerung auslöst) verursacht keine ArrangeOverride auf der verschachtelten MapOverlay aufgerufen werden. Dadurch wird die Route nicht mehr richtig positioniert - sie wird nicht skaliert.
Irgendwelche Vorschläge, warum die Ungültigkeit der Anordnung nicht auf das verschachtelte MapOverlay hinunterrieselt und/oder Tipps, wie man es beheben kann?
Nachtrag: Die Route wurde nur korrekt platziert, wenn die Karte anfänglich auf ihrem ersten Element positioniert wurde - die Breite/Länge der Route als Ganzes ist ein separates Problem, das ich gerne begrüßen würde.
Wenn Sie interessiert sind, könnte ich Sie sollten eine Route (d. H. Kreise mit Linien verbunden) mit meinem [XAML MapControl] (http://xamlmapcontrol.codeplex.com/) leicht anzuzeigen. MVVM natürlich. – Clemens
Ich habe Ihr Projekt erwähnt - das wäre sehr hilfreich! Vielen Dank! – Methalous
Wie zoomen Sie? Ich würde eine TransformGroup in der RenderTransform für den Stamm der Map verwenden, die über eine ScaleTransform- und TranslateTransform-Funktion verfügt, die das Zoomen und Verschieben steuert. Wie beim Render-Durchlauf würde dies das Layout überhaupt nicht beeinflussen. Außerdem stehen verschiedene Zoomsteuerungen aus verschiedenen Quellen zur Verfügung, mit denen Sie diesen Aspekt steuern können, ohne sich um das Layout in Ihrer Karte kümmern zu müssen. – Will