Maps for WPF
マーカー

A marker is used in maps to display location using shapes or images. The Map control allows you to create your own custom markers, and use images as markers, and add it to the VectorLayer, which represents a map layer with the shapes, vectors or geometries in geographical coordinates.

A map image with balloon markers.

The following code snippet describes how to add markers on a map surface.

 VectorLayer vl;
        Random rnd = new Random();
        VectorPlacemark current = null;
        Point offset = new Point();
        int idx = 1;
        public Marks()
        {
            InitializeComponent();
            Tag = "Marks";
            vl = new VectorLayer();
            maps.Layers.Add(vl);
            maps.MouseLeftButtonUp += new MouseButtonEventHandler(maps_MouseLeftButtonUp);
            for (int i = 0; i < 10; i++)
            {
                // ランダムな座標を作成します
                Point pt = new Point(-80 + rnd.Next(160), -80 + rnd.Next(160));
                AddMark(pt);
            }
        }
        void maps_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (Keyboard.Modifiers == ModifierKeys.Control)
            {
                AddMark(maps.ScreenToGeographic(e.GetPosition(maps)));
            }
        }
        void mark_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            VectorPlacemark pm = (VectorPlacemark)sender;
            if (Keyboard.Modifiers == ModifierKeys.Shift)
            {
                e.Handled = true;
                if (pm.CaptureMouse())
                {
                    current = pm;
                    offset = e.GetPosition(current);
                }
            }
            else if (Keyboard.Modifiers == ModifierKeys.Alt)
            {
                e.Handled = true;
                vl.Children.Remove(pm);
            }
        }
        void AddMark(Point pt)
        {
            Color clr = Utils.GetRandomColor(128, 192);
            VectorPlacemark mark = new VectorPlacemark()
            {
                GeoPoint = pt,
                Label = new TextBlock()
                {
                    RenderTransform = new TranslateTransform() { Y = -5 },
                    IsHitTestVisible = false,
                    Text = idx.ToString()
                },
                LabelPosition = LabelPosition.Top,
                Geometry = Utils.CreateBaloon(),
                Stroke = new SolidColorBrush(Colors.DarkGray),
                Fill = new SolidColorBrush(clr),
            };
            mark.MouseLeftButtonDown += new MouseButtonEventHandler(mark_MouseLeftButtonDown);
            mark.MouseLeftButtonUp += new MouseButtonEventHandler(mark_MouseLeftButtonUp);
            mark.MouseMove += new MouseEventHandler(mark_MouseMove);
            vl.Children.Add(mark);
            vl.LabelVisibility = LabelVisibility.Visible;
            idx++;
        }
        void mark_MouseMove(object sender, MouseEventArgs e)
        {
            if (current != null)
            {
                Point pt = e.GetPosition(maps);
                pt.X -= offset.X; pt.Y -= offset.Y;
                current.GeoPoint = maps.ScreenToGeographic(pt);
            }
        }
        void mark_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            VectorPlacemark pm = (VectorPlacemark)sender;
            if (pm != null)
                pm.ReleaseMouseCapture();
            current = null;
        }

Here, we created a class Utils for creating a balloon shaped marker using custom function CreateBaloon().

public class Utils
  {
    public static Geometry CreateBaloon()
    {
      PathGeometry pg = new PathGeometry();
      pg.Transform = new TranslateTransform() { X = -10, Y = -24.14 };
      PathFigure pf = new PathFigure() { StartPoint = new Point(10, 24.14), IsFilled = true, IsClosed = true };
      pf.Segments.Add(new ArcSegment() { SweepDirection = SweepDirection.Counterclockwise, Point = new Point(5, 19.14), RotationAngle = 45, Size = new Size(10, 10) });
      pf.Segments.Add(new ArcSegment() { SweepDirection = SweepDirection.Clockwise, Point = new Point(15, 19.14), RotationAngle = 270, Size = new Size(10, 10), IsLargeArc = true });
      pf.Segments.Add(new ArcSegment() { SweepDirection = SweepDirection.Counterclockwise, Point = new Point(10, 24.14), RotationAngle = 45, Size = new Size(10, 10) });
      pg.Figures.Add(pf);
      return pg;
    }
    public static void LoadShapeFromResource(VectorLayer vl, string resname, string dbfname, Location location, bool clear, ProcessShapeItem pv)
    {
        using (Stream shapeStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resname))
        {
            using (Stream dbfStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(dbfname))
            {
                if (shapeStream != null)
                {
                    if (clear)
                        vl.Children.Clear();
                    vl.LoadShape(shapeStream, dbfStream, location, true, pv);
                }
            }
        }
    }
   
    public static void LoadKMZFromResources(VectorLayer vl, string resname, bool clear, ProcessVectorItem pv)
    {
      using (Stream zipStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resname))
      {
        if (zipStream != null)
        {
          if( clear)
            vl.Children.Clear();
          vl.LoadKMZ(zipStream, true, pv);
        }
      }
    }
    public static void LoadKMLFromResources(VectorLayer vl, string resname, bool clear, ProcessVectorItem pv)
    {
        using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resname))
        {
            if (stream != null)
            {
                if (clear)
                    vl.Children.Clear();
                vl.LoadKML(stream, false, pv);
            }
        }
    }
    static Random rnd = new Random();
    public static Color GetRandomColor(byte a)
    {
      return Color.FromArgb(a, (byte)rnd.Next(255), (byte)rnd.Next(255), (byte)rnd.Next(255));
    }
    public static Color GetRandomColor(byte min, byte a)
    {
      return Color.FromArgb(a, (byte)( min + rnd.Next(255-min)),
        (byte)(min + rnd.Next(255-min)), (byte)(min + rnd.Next(255-min)));
    }
  }