本文整理自網路文章《MapX從資料庫讀取資料形成新圖層(C#)》,解決兩大問題:
DataTable 轉 COM ADODB.Recordset (MapX 僅支援 ADO)using ADODB;
using System.Data;
public sealed class AdoNetToAdo
{
public static Recordset ConvertDataTableToRecordset(DataTable table)
{
var rs = new RecordsetClass();
// 1. 建立欄位對應
foreach (DataColumn dc in table.Columns)
rs.Fields.Append(dc.ColumnName, GetAdoType(dc.DataType), -1, FieldAttributeEnum.adFldIsNullable, Missing.Value);
rs.Open(Missing.Value, Missing.Value, CursorTypeEnum.adOpenUnspecified, LockTypeEnum.adLockUnspecified, -1);
// 2. 逐列填入資料
foreach (DataRow dr in table.Rows)
{
rs.AddNew(Missing.Value, Missing.Value);
for (int i = 0; i < table.Columns.Count; i++)
rs.Fields[i].Value = dr[i];
}
return rs;
}
private static DataTypeEnum GetAdoType(Type netType) => netType.ToString() switch
{
"System.Boolean" => DataTypeEnum.adBoolean,
"System.Byte" => DataTypeEnum.adUnsignedTinyInt,
"System.Char" => DataTypeEnum.adChar,
"System.DateTime" => DataTypeEnum.adDate,
"System.Decimal" => DataTypeEnum.adDecimal,
"System.Double" => DataTypeEnum.adDouble,
"System.Int16" => DataTypeEnum.adSmallInt,
"System.Int32" => DataTypeEnum.adInteger,
"System.Int64" => DataTypeEnum.adBigInt,
"System.SByte" => DataTypeEnum.adTinyInt,
"System.Single" => DataTypeEnum.adSingle,
"System.String" => DataTypeEnum.adVarChar,
"System.UInt16" => DataTypeEnum.adUnsignedSmallInt,
"System.UInt32" => DataTypeEnum.adUnsignedInt,
"System.UInt64" => DataTypeEnum.adUnsignedBigInt,
_ => throw new Exception($"無對應 ADO 型別: {netType}")
};
}
private void DeleteLayerByName(string name)
{
for (int i = 1; i <= axMap1.Layers.Count; i++)
if (axMap1.Layers[i].Name == name) { axMap1.Layers.Remove(i); break; }
}
private void CreateLayerFromDB(string layerName, Recordset rs)
{
DeleteLayerByName(layerName);
// 1. 定義欄位結構
var flds = new MapXLib.FieldsClass();
flds.Add("stationid", "theid", MapXLib.AggregationFunctionConstants.miAggregationIndividual, MapXLib.FieldTypeConstants.miTypeString);
flds.Add("address", "address", MapXLib.AggregationFunctionConstants.miAggregationIndividual, MapXLib.FieldTypeConstants.miTypeString);
flds.Add("longitude", "longitude", MapXLib.AggregationFunctionConstants.miAggregationSum, MapXLib.FieldTypeConstants.miTypeNumeric); // 經度
flds.Add("latitude", "latitude", MapXLib.AggregationFunctionConstants.miAggregationSum, MapXLib.FieldTypeConstants.miTypeNumeric); // 緯度
// 2. 定義繫結圖層:XY 模式,指定經緯度欄位索引 (1-based)
var bindLayer = new MapXLib.BindLayerClass
{
LayerName = layerName,
RefColumn1 = 3, // longitude
RefColumn2 = 4, // latitude
LayerType = MapXLib.BindLayerTypeConstants.miBindLayerTypeXY
};
// 3. 加入 DataSet → 自動產生圖層
var ds = axMap1.DataSets.Add(
MapXLib.DatasetTypeConstants.miDataSetADO, rs, layerName,
"stationid", "address", bindLayer, flds, false);
// 4. 設定顯示風格:點位圖示
var layer = axMap1.Layers._Item(layerName);
layer.OverrideStyle = true;
const string icon = "icon.bmp"; // 需放於 MapX 安裝目錄 CUSTSYMB 資料夾
if (layer.Style.SupportsBitmapSymbols)
{
layer.Style.SymbolType = MapXLib.SymbolTypeConstants.miSymbolTypeBitmap;
layer.Style.SymbolBitmapSize = 60;
layer.Style.SymbolBitmapTransparent = true;
layer.Style.SymbolBitmapName = icon;
}
}
BindLayer.RefColumn1/2 為 1-based 索引,對應 Fields.Add 順序miBindLayerTypeXY 表示以經緯度直接定位,無需幾何欄位.bmp) 須置於 MapX CUSTSYMB 目錄