Code does these things :
- Add multiple point under one layer.
- Each point has a different Image
- Each point has a unique label which can be configured
public void LoadMarkers() { try { //uxMap represents the DotSpatial.Control.Map instance double[] dd1 = new double[] { 4.99, 52.673321 }; double[] dd2 = new double[] { 5.21, 52.912433 }; double[] dd3 = new double[] { 5.82, 53.581653 }; List<double[]> list = new List<double[]>(); list.Add(dd1); list.Add(dd2); list.Add(dd3); //Do something similar with images Image img1 = Image.FromFile(@"C:\file1.png"); Image img2 = Image.FromFile(@"C:\file2.png"); Image img3 = Image.FromFile(@"C:\file3.png"); List<Image> listImg = new List<Image>(); listImg.Add(img1); listImg.Add(img2); listImg.Add(img3); FeatureSet pointCoords = new FeatureSet(DotSpatial.Topology.FeatureType.Point); pointCoords.Projection = uxMap.Projection; DataColumn column1 = new DataColumn("ID"); DataColumn column2 = new DataColumn("label"); pointCoords.DataTable.Columns.Add(column1); pointCoords.DataTable.Columns.Add(column2); pointCoords.Projection = uxMap.Projection; DotSpatial.Symbology.IFeatureLayer fl = uxMap.Layers.Add(pointCoords); MapLabelLayer ll = new MapLabelLayer(); fl.LegendText = "<My Layer Name>"; fl.LabelLayer = ll; ll.Symbolizer = new DotSpatial.Symbology.LabelSymbolizer { FontFamily = "Tahoma", FontColor = Color.Black, FontSize = 8, BackColor = Color.White, BackColorEnabled = true, BackColorOpacity = 0.5f }; int pointID = 1; DotSpatial.Symbology.PointScheme pointScheme = new DotSpatial.Symbology.PointScheme(); pointScheme.ClearCategories(); foreach (var fe in list) { double x = fe[0]; double y = fe[1]; // I use a custom class to set the coordinates of the points. // You may have to use your own depending on your projection. System.Windows.Point pLo = LatLonToMeters(y, x); DotSpatial.Topology.Coordinate c = new DotSpatial.Topology.Coordinate(pLo.X, pLo.Y); DotSpatial.Topology.Point point = new DotSpatial.Topology.Point(c); IFeature currentFeature = pointCoords.AddFeature(point); currentFeature.DataRow["ID"] = pointID; currentFeature.DataRow["label"] = "point #" + pointID.ToString(); DotSpatial.Symbology.PictureSymbol pis = new DotSpatial.Symbology.PictureSymbol(); DotSpatial.Symbology.PointCategory pc = new DotSpatial.Symbology.PointCategory(pis); foreach (IFeature f in pointCoords.Features) { if (f.Coordinates[0] == currentFeature.Coordinates[0]) { //Here you can set any image you like. You can set one for each individual point. Image img = listImg[pointID - 1]; DotSpatial.Symbology.Size2D sz = new DotSpatial.Symbology.Size2D(img.Width, img.Height); pis.Image = img; pis.Size = sz; pc.Symbolizer.ScaleMode = DotSpatial.Symbology.ScaleMode.Simple; pc.FilterExpression = "[ID]='" + currentFeature.DataRow["ID"].ToString() + "'"; // <-- this is extremely important. Here the point ID is set pc.LegendText = currentFeature.DataRow["label"].ToString(); pointScheme.AddCategory(pc); ll.Symbology.Categories[0].Expression = "[" + fl.DataSet.DataTable.Columns[1].ColumnName + "]"; // <-- again, extremely important. Here the label value is set (Set to the point ID) } } pointID++; // bump up the ID's with one } fl.Symbology = pointScheme; fl.ApplyScheme(pointScheme); fl.ShowLabels = true; // <-- without this set, the labels won't show //Some built in Invoking just in case you work from a different thread as I tend to do if (InvokeRequired) { Invoke(new System.Windows.Forms.MethodInvoker(delegate { uxMap.Invalidate(); uxMap.Refresh(); })); } else { uxMap.Invalidate(); uxMap.Refresh(); } } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } private const int TileSize = 256; private const int EarthRadius = 6378137; private const double InitialResolution = 2 * Math.PI * EarthRadius / TileSize; private const double OriginShift = 2 * Math.PI * EarthRadius / 2; //Converts given lat/lon in WGS84 Datum to XY in Spherical Mercator EPSG:900913 public static System.Windows.Point LatLonToMeters(double lat, double lon) { var p = new Point(); p.X = lon * OriginShift / 180; p.Y = Math.Log(Math.Tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180); p.Y = p.Y * OriginShift / 180; return p; }