在Windows Forms C#中用ThinkGeo MapView实现多边形点击高亮的更优方案
在Windows Forms C#中用ThinkGeo实现多边形点击高亮的优化方案
问题背景
在Windows Forms C#环境下,使用ThinkGeo实现鼠标点击选中多边形并高亮其边框的功能,当前已通过新增一个仅包含点击位置多边形的高亮图层实现该功能,但想寻求更简洁、优雅的实现方案。现有代码如下:
... 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(); } }
优化方案
方案1:利用Feature的Selected状态+内置选中样式
无需额外创建高亮图层,直接给原多边形图层配置默认样式和选中样式,通过标记Feature的Selected属性控制显示状态,更贴合ThinkGeo的设计逻辑。
初始化图层时配置样式:
// 配置原多边形图层的默认样式 inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = new AreaStyle(new GeoPen(GeoColors.Black, 1), new GeoSolidBrush(GeoColors.LightSkyBlue)); // 配置选中时的高亮样式(黄色粗边框+透明填充) inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultSelectedAreaStyle = new AreaStyle(new GeoPen(GeoColors.Yellow, 4), new GeoSolidBrush(GeoColors.Transparent)); inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
点击事件处理逻辑简化:
private async void MapView_MapClick(object sender, MapClickMapViewEventArgs e) { this.tabControlMain.SelectedTab = tabPageMap; PointShape clickedPoint = e.WorldLocation; // 清除所有已选中的Feature状态 foreach (var feature in inMemoryFeatureLayer.InternalFeatures) { feature.Selected = false; } var clickedFeatures = inMemoryFeatureLayer.QueryTools.GetFeaturesContaining(clickedPoint, ReturningColumnsType.NoColumns); if (clickedFeatures.Count > 0) { // 标记点击的Feature为选中状态 clickedFeatures[0].Selected = true; } // 仅刷新原多边形图层,提升性能 await mapView.RefreshAsync(mapView.CurrentExtent, inMemoryFeatureLayer); }
方案2:使用ThinkGeo内置HighlightStyle机制
ThinkGeo提供了HighlightStyle和HighlightedFeatureIds集合,可直接指定需要高亮的Feature,无需维护额外图层或修改Feature状态。
初始化时配置高亮样式:
// 配置原多边形图层的默认样式 inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = new AreaStyle(new GeoPen(GeoColors.Black, 1), new GeoSolidBrush(GeoColors.LightSkyBlue)); inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; // 设置图层的高亮样式 var highlightStyle = new AreaStyle(new GeoPen(GeoColors.Yellow, 4), new GeoSolidBrush(GeoColors.Transparent)); inMemoryFeatureLayer.HighlightStyle = highlightStyle;
点击事件处理逻辑:
private async void MapView_MapClick(object sender, MapClickMapViewEventArgs e) { this.tabControlMain.SelectedTab = tabPageMap; PointShape clickedPoint = e.WorldLocation; // 清空之前的高亮Feature集合 inMemoryFeatureLayer.HighlightedFeatureIds.Clear(); var clickedFeatures = inMemoryFeatureLayer.QueryTools.GetFeaturesContaining(clickedPoint, ReturningColumnsType.NoColumns); if (clickedFeatures.Count > 0) { // 添加点击的Feature到高亮集合 inMemoryFeatureLayer.HighlightedFeatureIds.Add(clickedFeatures[0].Id); } // 仅刷新目标图层 await mapView.RefreshAsync(mapView.CurrentExtent, inMemoryFeatureLayer); }
额外优化建议
- 缩小刷新范围:刷新时指定具体图层而非整个地图,减少渲染开销
- 复用样式对象:将样式定义为类级别的静态常量,避免每次初始化重复创建对象
- 异步操作规范:确保异步调用正确使用
await,避免UI线程阻塞
内容的提问来源于stack exchange,提问作者Pepik
相关产品推荐
相关产品推荐

