You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 18:44:57