MapObjects 2.x 是 ESRI 早期 GIS ActiveX 控制項套件,廣泛用於 2000 年代 WinForms 桌面應用。雖已停止更新,但存量專案維護仍有需求。本文示範 C# 透過 AxInterop/Interop 組件動態載入 Shapefile 圖層。
AxMapObjects2.dll (ActiveX Wrapper) + MapObjects2.dll (RCW)。AxMap 控制項 (命名 axMap1)。using System;
using System.Windows.Forms;
using MapObjects2; // RCW 命名空間
using AxMapObjects2; // ActiveX Wrapper
namespace MapObjectsLoader
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
Load += MainForm_Load;
}
private void MainForm_Load(object sender, EventArgs e)
{
try
{
// 1. 建立資料連接 (Shapefile 工作區)
var dc = new DataConnectionClass();
// Shapefile 目錄 (非單一檔案)
string shapeDir = Application.StartupPath; // 或設定檔路徑
dc.Database = shapeDir;
if (!dc.Connect())
{
MessageBox.Show($"無法連接資料目錄: {shapeDir}", "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
// 2. 依繪製順序載入圖層:面 → 線 → 點 (底圖在下)
string[] layerNames = { "States", "Rivers", "Cities" }; // 對應 .shp 檔名 (不含副檔名)
foreach (string name in layerNames)
{
var layer = new MapLayerClass();
layer.GeoDataset = dc.FindGeoDataset(name);
if (layer.GeoDataset == null)
{
System.Diagnostics.Debug.WriteLine($"圖層 '{name}' 不存在於目錄中");
continue;
}
axMap1.Layers.Add(layer);
System.Diagnostics.Debug.WriteLine($"已載入圖層: {name}, 要素數: {layer.FeatureCount}");
}
// 3. 設定初始範圍 (全圖層範圍)
axMap1.Extent = axMap1.FullExtent;
// 4. 重繪
axMap1.Refresh();
}
catch (Exception ex)
{
MessageBox.Show($"載入地圖失敗: {ex.Message}", "異常", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
| 類別 | 用途 | 常用成員 |
|---|---|---|
DataConnection | 資料源連接 (Shapefile, Access, SDE...) | Database (路徑), Connect(), FindGeoDataset(name) |
MapLayer | 單一圖層 (幾何+符號+標註) | GeoDataset, Visible, Renderer, LabelRenderer |
Map (AxMap) | 地圖容器、視圖控制 | Layers, Extent, FullExtent, Refresh(), MousePointer |
Feature | 單一地理要素 | Shape, Fields, Value(field) |
Shape | 幾何體 | Type (Point/Polygon/Polyline), Area, Length |
.shp, .shx, .dbf 三檔齊全。FindGeoDataset("States") 需與檔名完全一致。axMap1.Layers.Add(layer) 將新圖層置於**最上層**。
載入順序 = 繪製順序 (先載入 = 底圖)。
protected override void OnFormClosing(FormClosingEventArgs e)
{
// 明確釋放 ActiveX 資源
if (axMap1 != null)
{
axMap1.Layers.Clear();
axMap1.Dispose(); // 呼叫 AxHost.Dispose
}
base.OnFormClosing(e);
}
MapObjects 2.x 為 32-bit ActiveX,**專案必須設定 Prefer 32-bit 或 Platform target: x86**,否則 AxInterop 載入失敗 (BadImageFormatException)。
| 庫 | 授權 | 特色 | 遷移難度 |
|---|---|---|---|
| ArcGIS Runtime SDK for .NET | 商業 | ESRI 官方現代化、3D、離線、行動端 | 高 (API 全異) |
| DotSpatial | LGPL | 純 .NET、Shapefile/GeoJSON、投影轉換 | 中 |
| SharpMap | GPL | 輕量、OGC 標準、渲染引擎可替換 | 中 |
| NetTopologySuite (NTS) | BSD | 幾何運算核心、配合 GeoAPI、無 UI | 低 (僅幾何) |
| MapControl (WinForms/WPF) | MIT | 現代 UI、向量瓦片、MVVM 友善 | 中 |
維護舊系統時,掌握 AxInterop 互操作、COM 釋放、x86 強制等細節至關重要;新專務請直接投入現代純 .NET GIS 生態系。