ArcEngine|加载不同类型文档并实现TOCControl的右键菜单
所有的代码已经传到了我的GitHub,需要的请自取,GitHub项目地址:https://github.com/Weltra/T_ArcMap
MapControl中加载不同类型文档
加载ShapeFile
在file选项下添加Open file选项,并在其子选项中添加Open Shapefile选项。为其绑定Click事件。
在Click事件的方法中添加代码,实现加载shape的功能。
private void openShapefileToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog openshapeFileDialog = new OpenFileDialog();
openshapeFileDialog.Filter = "地图文档(*.shp)|*.shp";
openshapeFileDialog.Title = "Selcet a ShapeFile";
if (openshapeFileDialog.ShowDialog() == DialogResult.OK)
{
string FilePath = openshapeFileDialog.FileName;
string FileName = openshapeFileDialog.SafeFileName;
string WorkspacePath = FilePath.Replace(FileName,"");
IWorkspaceFactory shapefileworkspace = new ShapefileWorkspaceFactory();
IFeatureWorkspace pWorkSpace = shapefileworkspace.OpenFromFile(WorkspacePath, 0) as IFeatureWorkspace;
IFeatureClass pfeatureclass = pWorkSpace.OpenFeatureClass(FileName);
IFeatureLayer featureLayer = new FeatureLayer();
featureLayer.FeatureClass = pfeatureclass;
featureLayer.Name = pfeatureclass.AliasName;
featureLayer.Visible = true;
IMap pmap = axMapControl1.Map;
pmap.AddLayer(featureLayer);
axMapControl1.ActiveView.Refresh();
}
}
封装加载空间数据库方法
新建一个FileClass,封装加载空间数据库方法:AddAllDataset函数,以便对其他空间数据库加载时直接调用。
class FileClass
{
//封装加载空间数据库方法:AddAllDataset函数,以便对其他空间数据库加载时直接调用。
public static void AddAllDataset(IWorkspace pWorkspace, AxMapControl mapControl)
{
IEnumDataset pEnumDataset = pWorkspace.get_Datasets(ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTAny);
pEnumDataset.Reset();
//将Enum数据集集中的数据一个一个地读到dataset 中
IDataset pDataset = pEnumDataset.Next();
//判断数据集是否有数据
while (pDataset != null)
{
if (pDataset is IFeatureDataset)//要素数据集
{
IFeatureWorkspace pFeatureWorkspac = (IFeatureWorkspace)pWorkspace;
IFeatureDataset pFeatureDataset = pFeatureWorkspac.OpenFeatureDataset(pDataset.Name);
IEnumDataset pEnumDataset1 = pFeatureDataset.Subsets;
pEnumDataset1.Reset();
IGroupLayer pGroupLayer = new GroupLayerClass();
pGroupLayer.Name = pFeatureDataset.Name;
IDataset pDataset1 = pEnumDataset1.Next();
while (pDataset1 != null)
{
if (pDataset1 is IFeatureClass)//要素类
{
IFeatureLayer pFeatureLayer = new FeatureLayerClass();
pFeatureLayer.FeatureClass = pFeatureWorkspac.OpenFeatureClass(pDataset1.Name);
if (pFeatureLayer.FeatureClass != null)
{
pFeatureLayer.Name = pFeatureLayer.FeatureClass.AliasName;
pGroupLayer.Add(pFeatureLayer);
mapControl.Map.AddLayer(pFeatureLayer);
}
}
pDataset1 = pEnumDataset1.Next();
}
}
else if (pDataset is IFeatureClass)//要素类
{
IFeatureWorkspace pFeatureWorkspace = (IFeatureWorkspace)pWorkspace;
IFeatureLayer pFeatureLayer = new FeatureLayerClass();
pFeatureLayer.FeatureClass = pFeatureWorkspace.OpenFeatureClass(pDataset.Name);
pFeatureLayer.Name = pFeatureLayer.FeatureClass.AliasName;
mapControl.Map.AddLayer(pFeatureLayer);
}
else if (pDataset is IRasterDataset)//栅格数据
{
IRasterWorkspaceEx pRasterWorkspace = (IRasterWorkspaceEx)pWorkspace;
IRasterDataset pRasterDataset = pRasterWorkspace.OpenRasterDataset(pDataset.Name);
//影像金字塔的判断和创建
IRasterPyramid3 pRasterPyramid;
pRasterPyramid = pRasterDataset as IRasterPyramid3;
if (pRasterPyramid != null)
{
if (!(pRasterPyramid.Present))
{
pRasterPyramid.Create();//创建金字塔
}
}
IRasterLayer pRasterLayer = new RasterLayerClass();
pRasterLayer.CreateFromDataset(pRasterDataset);
ILayer pLayer = pRasterLayer as ILayer;//进行继承
mapControl.AddLayer(pLayer, 0);
}
pDataset = pEnumDataset.Next();
}
mapControl.ActiveView.Refresh();
//同步鹰眼
// SynchronizeEagleEye();
}
}
加载Access Geodatabase
在Open file选项的子选项中添加Open mdb file选项,为其绑定Click事件。在Click事件处理方法中添加代码,实现加载Access Geodatabase的功能。
在Click事件的方法中添加代码,实现加载mdb的功能。
private void openMdbFileToolStripMenuItem_Click(object sender, EventArgs e)
{
OpenFileDialog pOpenFileDialog = new OpenFileDialog();
pOpenFileDialog.Title = "打开PersonGeoDatabase文件";
pOpenFileDialog.Filter = "Personal GeoDatabase(*.mdb)|*.mdb";
pOpenFileDialog.ShowDialog();
string pFullPath = pOpenFileDialog.FileName;
if (pFullPath == "") return;
AccessWorkspaceFactory pAccessWorkspaceFactory = new AccessWorkspaceFactory();
//获取工作空间
IWorkspace pWorkspace = pAccessWorkspaceFactory.OpenFromFile(pFullPath, 0);
//ClearAllData();
FileClass.AddAllDataset(pWorkspace, axMapControl1);
}
加载File Geodatabase
在Open file选项的子选项中添加Open gdb file选项,为其绑定Click事件。在Click事件处理方法中添加代码,实现加载File Geodatabase的功能。
在Click事件的方法中添加代码,实现加载gdb的功能。
private void openGdbFileToolStripMenuItem_Click(object sender, EventArgs e)
{
FolderBrowserDialog dlg = new System.Windows.Forms.FolderBrowserDialog();
if (dlg.ShowDialog() != DialogResult.OK) return;
string pFullth = dlg.SelectedPath;
if (pFullth == "") return;
//使用esri.arcgis.DataSourseGDB
FileGDBWorkspaceFactory pFileGDBWorkspaceFactory = new FileGDBWorkspaceFactory();
//ClearAllData();
//获取工作空间
IWorkspace pWorkspac = pFileGDBWorkspaceFactory.OpenFromFile(pFullth, 0);
FileClass.AddAllDataset(pWorkspac, axMapControl1);
}
实现右键菜单栏
添加ContextMenuStrip1控件,并在在该上下文菜单中添加“移除(R)”和“打开属性表(T)”菜单项。
添加ContextMenuStrip2控件,并在在该上下文菜单中添加“添加数据(T)”、“打开所有图层(Y)”和“关闭所有图层(L)”菜单项。
添加ContextMenuStrip3控件,并在在该上下文菜单中添加“更改颜色(C)”菜单项。
首先添加axTOCControl1的OnMouseDown事件。选中窗体上axTOCControl1,双击添加OnMouseDown事件。
在图层处右击会弹出上下文菜单,移除和打开属性表都是针对所选图层来操作的,ITOCControl.HitTest方法可以使我们在Engine中鼠标右击TocControl时得到选择的图层。声明 m_Layer为全局变量,然后在OnMouseDown事件中添加如下代码。
private void axTOCControl1_OnMouseDown(object sender, ESRI.ArcGIS.Controls.ITOCControlEvents_OnMouseDownEvent e)
{
if (e.button == 2)
{
ESRI.ArcGIS.Controls.esriTOCControlItem Item = ESRI.ArcGIS.Controls.esriTOCControlItem.esriTOCControlItemNone;
IBasicMap pBasicMap = null;
ILayer pLayer = null;
object other = null;
object index = null;
axTOCControl1.HitTest(e.x, e.y, ref Item, ref pBasicMap, ref pLayer, ref other, ref index);
m_Layer = pLayer;
switch (Item)
{
case ESRI.ArcGIS.Controls.esriTOCControlItem.esriTOCControlItemHeading:
contextMenuStrip2.Show(axTOCControl1, new System.Drawing.Point(e.x, e.y));
break;
case ESRI.ArcGIS.Controls.esriTOCControlItem.esriTOCControlItemLayer:
contextMenuStrip1.Show(axTOCControl1, new System.Drawing.Point(e.x, e.y));
break;
case ESRI.ArcGIS.Controls.esriTOCControlItem.esriTOCControlItemLegendClass:
contextMenuStrip3.Show(axTOCControl1, new System.Drawing.Point(e.x, e.y));
break;
case ESRI.ArcGIS.Controls.esriTOCControlItem.esriTOCControlItemMap:
contextMenuStrip4.Show(axTOCControl1, new System.Drawing.Point(e.x, e.y));
break;
case ESRI.ArcGIS.Controls.esriTOCControlItem.esriTOCControlItemNone:
contextMenuStrip5.Show(axTOCControl1, new System.Drawing.Point(e.x, e.y));
break;
}
}
}
实现Remove Layer
首先添加该菜单项的Click事件,然后在“Remove Layer”的Click事件中添加如下代码。
private void 移除ToolStripMenuItem_Click(object sender, EventArgs e)
{
axMapControl1.Map.DeleteLayer(m_Layer);
}
实现Open Atrribute Table
首先添加该菜单项的Click事件,然后需要新建窗体用来显示属性表。具体为选中该工程右击,下拉列表中选择Add->Windows Form,为其窗体命名为“Attribute_Table”,点击“Add”。为新建窗体添加DataGridView,然后选中该DataGridView,设置其Dock选项为Fill。
为窗体的Load事件添加代码。该事件处理主要是从图层中读取要素类的属性信息,并且显示到DataGridView控件中。
private void Atrribute_Table_Load(object sender, EventArgs e)
{
IFields pFields;
pFields = pFeatureLayer.FeatureClass.Fields;
dataGridView1.ColumnCount = pFields.FieldCount;
for (int i = 0; i < pFields.FieldCount; i++)
{
string fldName = pFields.get_Field(i).Name;
dataGridView1.Columns[i].Name = fldName;
dataGridView1.Columns[i].ValueType = System.Type.GetType(CoClass.ParseFieldType(pFields.get_Field(i).Type));
}
IFeatureCursor pFeatureCursor;
pFeatureCursor = pFeatureLayer.FeatureClass.Search(null, false);
IFeature pFeature;
pFeature = pFeatureCursor.NextFeature();
while (pFeature != null)
{
string[] fldValue = new string[pFields.FieldCount];
for (int i = 0; i < pFields.FieldCount; i++)
{
string fldName;
fldName = pFields.get_Field(i).Name;
if (fldName == pFeatureLayer.FeatureClass.ShapeFieldName)
{
fldValue[i] = Convert.ToString(pFeature.Shape.GeometryType);
}
else
fldValue[i] = Convert.ToString(pFeature.get_Value(i));
}
dataGridView1.Rows.Add(fldValue);
pFeature = pFeatureCursor.NextFeature();
}
}
因为ESRI的数据类型和系统数据类型有所区别,因此需要事先进行类型转换,将其封装在类CoClass中,通过ParseFieldType方法来实现:
class CoClass
{
//将ESRI类型转为系统类���
public static string ParseFieldType(esriFieldType fieldType)
{
switch (fieldType)
{
case esriFieldType.esriFieldTypeBlob:
return "System.String";
case esriFieldType.esriFieldTypeDate:
return "System.DateTime";
case esriFieldType.esriFieldTypeDouble:
return "System.Double";
case esriFieldType.esriFieldTypeGeometry:
return "System.String";
case esriFieldType.esriFieldTypeGlobalID:
return "System.String";
case esriFieldType.esriFieldTypeGUID:
return "System.String";
case esriFieldType.esriFieldTypeInteger:
return "System.Int32";
case esriFieldType.esriFieldTypeOID:
return "System.String";
case esriFieldType.esriFieldTypeRaster:
return "System.String";
case esriFieldType.esriFieldTypeSingle:
return "System.Single";
case esriFieldType.esriFieldTypeSmallInteger:
return "System.Int32";
case esriFieldType.esriFieldTypeString:
return "System.String";
default:
return "System.String";
}
}
}
在mainForm.cs的OpenAttributeTable的Click事件中添加代码。
private void OpenAttributeTableToolStripMenuItem1_Click(object sender, EventArgs e)
{
AttributeTable pAttributeTable = new AttributeTable(globe_Layer as IFeatureLayer);
pAttributeTable.Show();
}
结果
加载地图文档
加载ShapeFile
加载Access Geodatabase
加载File Geodatabase
TocControl图层控制
针对Layer
移除
打开属性表
针对Map
针对LegendClass
总结
简述工厂模式
工厂模式主要是为创建对象提供接口,将创建对象的过程隔离起来,实现了创建者与调用者的分离,提高了程序的灵活性。
核心本质:
实例化对象,用工厂方法代替new操作。
将选择实现类、创建对象统一管理和控制,从而将调用者跟我们实现类解耦。
加载Shape的步骤
创建工作空间工厂
打开shapefile工作空间
打开要素类
创建要素图层
关联图层和要素类
添加到地图空间
TocControl提供的HitTest方法的主要作用?
ITOCControl接口的HitTest()方法可以返回TOCControl中点击坐标点处的对象类型ItemType。具体定义如下:
public void HitTest ( int X, int Y, ref esriTOCControlItem ItemType, ref IBasicMap BasicMap, ref ILayer Layer, ref object Unk, ref object Data );
各参数的含义如下:
- X,Y :鼠标点击的坐标;
- ITemType: esriTOCControlItem枚举常量
- BasicMap:绑定MapControl的IBasicMap接口
- Layer:被点击的图层
- Unk:TOCControl的LegendGroup对象
- Data:LegendClass在LegendGroup中的Index。
esriTOCControlItem枚举常量用于描述TocControl上的Item的类型,其定义如下:

浙公网安备 33010602011771号