Is there a simpler, more elegant aproach to select a polygon and highlight it using MapView control from ThinkGeo ?
So far I have implented this approach. On mouse click I add predefined layer to the ThinkGeo MapView Overlay, this layer is a copy of the the "base" layer with all polygons but with only the one polygon on coordinates of the mouse click.
...
using System;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
using ThinkGeo.Core;
using ThinkGeo.UI.WinForms;
...
...
private async void frmFullScreenMaps_Load(object sender, EventArgs e)
{
this.control.SuspendLayout();
mapView = new ThinkGeo.UI.WinForms.MapView();
form.Controls.Add(this.mapView); // Add the control to the form
mapView.Location = new System.Drawing.Point(0, 0);
mapView.MapResizeMode = ThinkGeo.Core.MapResizeMode.PreserveScaleAndCenter;
mapView.MaximumScale = 1000000D;
mapView.MinimumScale = 100D;
mapView.RotatedAngle = 0F;
mapView.Size = new System.Drawing.Size(100, 100);
mapView.Dock = DockStyle.Fill;
mapView.MapUnit = GeographyUnit.Feet;
await mapView.RefreshAsync();
this.control.ResumeLayout(false);
this.control.PerformLayout();
...
...
// In memory layer - all polygons
inMemoryFeatureLayer = new InMemoryFeatureLayer();
...
...
// In memory layer - for the (one) selected polygon
inMemoryHighlighLayer = new InMemoryFeatureLayer();
//Styling the inMemoryHighlighLayer
inMemoryHighlighLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = new AreaStyle(new GeoPen(GeoColors.Yellow, 4), new GeoSolidBrush(GeoColors.Transparent));
inMemoryHighlighLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
inMemoryHighlighLayer.Open();
...
...
// Attach mapView Click event handler
maps.mapView.MapClick += MapView_MapClick;
await maps.mapView.RefreshAsync();
}
private async void MapView_MapClick(object sender, MapClickMapViewEventArgs e)
{
this.tabControlMain.SelectedTab = tabPageMap;
PointShape clickedPoint = e.WorldLocation;
// This assume the layer is already open, so we can query it
var clickedFeatures = inMemoryFeatureLayer.QueryTools.GetFeaturesContaining(clickedPoint, ReturningColumnsType.NoColumns);
if (clickedFeatures.Count > 0)
{
// Get the clicked feature
var clickedFeature = clickedFeatures[0];
// Add the clicked feature to the highlight layer
inMemoryHighlighLayer.InternalFeatures.Clear();
inMemoryHighlighLayer.InternalFeatures.Add(clickedFeature);
// Convert world coordinates to screen coordinates
var screenPoint = mapView.ToScreenCoordinate(clickedPoint);
await mapView.RefreshAsync(mapView.CurrentExtent, inMemHighlightOverlay); //zooms to parcel
}
else
{
// Clear the highlight layer if no feature was clicked
inMemoryHighlighLayer.InternalFeatures.Clear();
await mapView.RefreshAsync();
}
}
Your solution is correct, and probably the 'best' implementation. I know it's a little verbose to create a separate InMemoryFeatureLayer for just one shape, but there is very little performance overhead in the extra layer and it's more flexible having a full layer and more consistent with the api.
There is an alternative implementation using the MapShape class which will also work if you need different styles on each drawn shape, but in your instance the InMemoryFeatureLayer is probably better.
Please see below for the MapShape implementation just in case you want to try that route:
// First Initialize the MapShapesLayer as following:
var inMemHighlightOverlay = new LayerOverlay();
wpfMap.Overlays.Add(inMemHighlightOverlay);
var mapshapeLayer = new MapShapeLayer();
inMemHighlightOverlay.Layers.Add(mapshapeLayer);
// Then use the following code to add the feature to highlight
var mapShape = new MapShape(clickedFeature);
mapShape.ZoomLevels.ZoomLevel01.DefaultAreaStyle =
AreaStyle.CreateSimpleAreaStyle(GeoColors.Red);
mapShape.ZoomLevels.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
mapshapeLayer.MapShapes.Clear();
mapshapeLayer.MapShapes.Add("shape1", mapShape);
await inMemHighlightOverlay.RefreshAsync();