Вы, вероятно, могли бы сэкономить много работы, используя одну из библиотек управления картами, доступных для WPF. Я могу порекомендовать мой XAML Map Control . Он предоставляет несколько способов отображения растровых изображений на карте, а также имеет MapItemsControl
для простого отображения коллекций элементов с географическим расположением.
Вероятно, самый простой способ показать навигационную карту - это использовать WmsImageLayer
:
xmlns:map="clr-namespace:MapControl;assembly=MapControl.WPF"
...
<map:Map Center="50,0" ZoomLevel="2">
<map:Map.MapLayer>
<map:WmsImageLayer ServiceUri="http://chartserver4.sevencs.com:8080"
Layers="ENC"/>
</map:Map.MapLayer>
</map:Map>
Если у вас нет WMS для создания диаграмм (например, SevenCs ChartServer), но необходимо преобразовать растровое изображение WinForms, вы можете получить его из MapImageLayer
класса:
public class ChartImageLayer : MapImageLayer
{
protected override Task<ImageSource> GetImageAsync(BoundingBox boundingBox)
{
// use ParentMap.MapProjection to get the current map projection
return Task.Run(() =>
{
// get SevenCs chart bitmap for the requested bounding box
System.Drawing.Bitmap chartBitmap = ...
// convert from System.Drawing.Bitmap to System.Windows.Media.ImageSource
using (var stream = new MemoryStream())
{
chartBitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
stream.Position = 0;
var bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = stream;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
bitmapImage.Freeze();
return (ImageSource)bitmapImage;
}
});
}
}
и используйте класс следующим образом:
<map:Map Center="50,0" ZoomLevel="2">
<map:Map.MapLayer>
<local:ChartImageLayer />
</map:Map.MapLayer>
</map:Map>
Для отображения коллекций элементов вы должны создать модель вида, например, как это:
using MapControl;
...
public class Waypoint
{
public string Label { get; set; }
public Location Location { get; set; }
}
public class ViewModel
{
public ObservableCollection<Waypoint> Waypoints { get; }
= new ObservableCollection<Waypoint>();
}
с некоторой инициализацией, такой как:
public MainWindow()
{
InitializeComponent();
var vm = new ViewModel();
vm.Waypoints.Add(new Waypoint { Label = "Iceland", Location = new Location(65, -18) });
vm.Waypoints.Add(new Waypoint { Label = "Norway", Location = new Location(71, 25) });
vm.Waypoints.Add(new Waypoint { Label = "Cyprus", Location = new Location(35, 33) });
vm.Waypoints.Add(new Waypoint { Label = "Tenerife", Location = new Location(28.25, -16.5) });
DataContext = vm;
}
В XAML вы бы добавили MapItemsControl следующим образом:
<map:Map Center="50,0" ZoomLevel="2">
...
<map:MapItemsControl ItemsSource="{Binding Waypoints}">
<map:MapItemsControl.ItemContainerStyle>
<Style TargetType="map:MapItem">
<Setter Property="map:MapPanel.Location" Value="{Binding Location}"/>
</Style>
</map:MapItemsControl.ItemContainerStyle>
<map:MapItemsControl.ItemTemplate>
<DataTemplate>
<Canvas>
<Path Fill="Red">
<Path.Data>
<EllipseGeometry RadiusX="5" RadiusY="5"/>
</Path.Data>
</Path>
<TextBlock Margin="5,-5" Text="{Binding Label}"/>
</Canvas>
</DataTemplate>
</map:MapItemsControl.ItemTemplate>
</map:MapItemsControl>
</map:Map>
Результат:
Увеличено: