《GS软件设计》实习报告
}
3. 空间查询模块
属性查询
属性查询,实现对地图要素的查询,在ArcMap中,单击图层右键菜单中的“Open Attribute Table”命令,便可弹出属性数据表。下面完成类似的功能,效果如下:。
1.创建属性表窗体
新建一个Windows窗体,命名为“AttributeTableFrm.cs”。
从工具箱拖一个DataGridView控件到窗体,并将其Dock属性设置为“Fill”。 添加如下引用: using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.Controls; using ESRI.ArcGIS.esriSystem; using ESRI.ArcGIS.SystemUI; using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geodatabase;
2.创建空 DataTable
首先传入 ILayer,再查询到 ITable,从 ITable 中的 Fileds 中获得每个 Field,再根据 Filed 设置 DataTable 的 DataColumn,由
此创建一个只含图层字段的空 DataTable。实现函数如下:
private static DataTable CreateDataTableByLayer(ILayer pLayer, string tableName) {
//创建一个 DataTable 表
DataTable pDataTable = new DataTable(tableName); //取得 ITable 接口
ITable pTable = pLayer as ITable; IField pField = null;
DataColumn pDataColumn;
//根据每个字段的属性建立 DataColumn 对象 for (int i = 0; i < pTable.Fields.FieldCount; i++) {
pField = pTable.Fields.get_Field(i);
//新建一个 DataColumn 并设置其属性
pDataColumn = new DataColumn(pField.Name); if (pField.Name == pTable.OIDFieldName)
30
《GS软件设计》实习报告
{
pDataColumn.Unique = true;//字段值是否唯一 }
pDataColumn.AllowDBNull = pField.IsNullable; pDataColumn.Caption = pField.AliasName;
pDataColumn.DataType = System.Type.GetType(ParseFieldType(pField.Type)); pDataColumn.DefaultValue = pField.DefaultValue; if (pField.VarType == 8) {
pDataColumn.MaxLength = pField.Length; }
//字段添加到表中
pDataTable.Columns.Add(pDataColumn); pField = null;
pDataColumn = null; }
return pDataTable; }
因为 GeoDatabase 的数据类型与.NET 的数据类型不同,故要进行转换。转换函数如下: public static string ParseFieldType(esriFieldType fieldType) {
switch (fieldType)
{
case esriFieldType.esriFieldTypeBlob: return \
case esriFieldType.esriFieldTypeDate: return \
case esriFieldType.esriFieldTypeDouble: return \
case esriFieldType.esriFieldTypeGeometry: return \
case esriFieldType.esriFieldTypeGlobalID: return \
case esriFieldType.esriFieldTypeGUID: return \
case esriFieldType.esriFieldTypeInteger: return \
case esriFieldType.esriFieldTypeOID: return \
case esriFieldType.esriFieldTypeRaster: return \
case esriFieldType.esriFieldTypeSingle: return \
case esriFieldType.esriFieldTypeSmallInteger: return \
case esriFieldType.esriFieldTypeString: return \default:
return \} }
3.装载 DataTable 数据
从上一步得到的 DataTable 还没有数据,只有字段信息。因此,我们要通过 ICursor 从 ITable 中逐一取出每一行数据,即 IRow。
再创建 DataTable 中相应的 DataRow,根据 IRow 设置 DataRow 信息,再将所有的 DataRow 添加到 DataTable 中,就完成了 DataTable 数据的装载。
为保证效率,一次最多只装载 2000 条数据到 DataGridView。函数代码如下: public static DataTable CreateDataTable(ILayer pLayer, string tableName) {
DataTable pDataTable = CreateDataTableByLayer(pLayer, tableName); string shapeType = getShapeType(pLayer); DataRow pDataRow = null;
31
《GS软件设计》实习报告
ITable pTable = pLayer as ITable;
ICursor pCursor = pTable.Search(null, false); IRow pRow = pCursor.NextRow(); int n = 0;
while (pRow != null) {
pDataRow = pDataTable.NewRow();
for (int i = 0; i < pRow.Fields.FieldCount; i++) {
if (pRow.Fields.get_Field(i).Type == esriFieldType.esriFieldTypeGeometry) {
pDataRow[i] = shapeType; }
else if (pRow.Fields.get_Field(i).Type == esriFieldType.esriFieldTypeBlob) {
pDataRow[i] = \}
else {
pDataRow[i] = pRow.get_Value(i); } }
//添加 DataRow 到 DataTable pDataTable.Rows.Add(pDataRow); pDataRow = null; n++;
if (n == 2000) {
pRow = null; } else {
pRow = pCursor.NextRow(); } }
return pDataTable; }
上面的代码中涉及到一个获取图层类型的函数 getShapeTape,此函数是通过 ILayer 判断图层类型的,代码如下:
public static string getShapeType(ILayer pLayer) {
IFeatureLayer pFeatLyr = (IFeatureLayer)pLayer; switch (pFeatLyr.FeatureClass.ShapeType) {
case esriGeometryType.esriGeometryPoint: return \
case esriGeometryType.esriGeometryPolyline: return \
case esriGeometryType.esriGeometryPolygon: return \default: return \} }
4.绑定 DataTable 到 DataGridView
通过以上步骤,我们已经得到了一个含有图层属性数据的 DataTable。现定义一个 AttributeTableFrm 类的成员变量:
public DataTable attributeTable;
通过以下函数,我们很容易将其绑定到 DataGridView 控件中。 public void CreateAttributeTable(ILayer player)
32
《GS软件设计》实习报告
{
string tableName;
tableName = getValidFeatureClassName(player .Name ); attributeTable = CreateDataTable(player,tableName ); this.dataGridView1 .DataSource = attributeTable ;
this.Text = \属性表[\记录数:\ }
因为 DataTable 的表名不允许含有“.”,因此我们用“_”替换。函数如下: public static string getValidFeatureClassName(string FCname) {
int dot = FCname.IndexOf(\ if (dot != -1) {
return FCname.Replace(\}
return FCname; }
5.调用属性表窗体
通过 1-4 步骤,我们封装了一个 AttributeTableFrm 类,此类能够由 ILayer 显示图层中的属性表数据。那怎么调用 AttributeTableFrm 呢?
前面已经提到,我们是在 TOCControl 选中图层的右键菜单中弹出属性表窗体的,因此我们需要添加一个菜单项到 TOCControl
中Layer 的右键菜单。而在第六讲中,我们采用的是AE 中的 IToolbarMenu 实现右键菜单的,故我们还需自定义一个 Command, 实现打开属性表的功能。
以 ArcGIS 的 Base Command 为模板新建项“OpenAttributeTable.cs”。
注意:新建 Base Command 模板时,会弹出一个对话框让我们选择模板适用对象,这时我们要选择 MapControl 、
PageLayoutControl,即选择第二项或者倒数第二项。
添加如下引用:
using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.Display; using ESRI.ArcGIS.esriSystem;
添加成员变量:
private ILayer m_pLayer;
修改构造函数为:
public OpenAttributeTable(ILayer pLayer) {
base.m_category = \
base.m_caption = \打开属性表\base.m_message = \打开属性表\ base.m_toolTip = \打开属性表\
base.m_name = \打开属性表\m_pLayer = pLayer; try {
string bitmapResourceName = GetType().Name + \
base.m_bitmap = new Bitmap(GetType(), bitmapResourceName); }
catch (Exception ex) {
33
《GS软件设计》实习报告
System.Diagnostics.Trace.WriteLine(ex.Message, \} }
再在 On_Click 函数中添加如下代码,以创建并打开属性表窗体。 public override void OnClick()
{AttributeTableFrm attributeTable = new AttributeTableFrm(); attributeTable.CreateAttributeTable(m_pLayer); attributeTable.ShowDialog(); }
至此,我们完成了 OpenAttributeTable 命令。显然,我们要在 TOCControl 的 OnMouseDown 事件中调用此命令。
因为,当前选中的图层参数,即 ILayer 是通过 OpenAttributeTable 的构造函数传入的,而选中的 ILayer 是动态变化的,所以
我们无法在窗体初始化的 OnMouseDown
Form1_Load 事件中就添加 OpenAttributeTable 菜单项到右键菜单。但我们可以在
事件中动态添加 OpenAttributeTable 菜单项。
要注意的是,最后我们必须移除添加的 OpenAttributeTable 菜单项,不然每次按下右键都会添加此菜单项,将造成右键菜单
中含有多个 OpenAttributeTable 菜单项。
修改 TOCControl 的 OnMouseDown 事件的部分代码如下:
private void axTOCControl1_OnMouseDown(object sender, ITOCControlEvents_OnMouseDownEvent e) {
if (item == esriTOCControlItem.esriTOCControlItemMap) m_menuMap.PopupMenu(e.x, e.y, m_tocControl.hWnd); if (item == esriTOCControlItem.esriTOCControlItemLayer) {
m_menuLayer.AddItem(new OpenAttributeTable(layer), -1, 2, true, esriCommandStyles.esriCommandStyleTextOnly);
m_menuLayer.PopupMenu(e.x, e.y, m_tocControl.hWnd); m_menuLayer.Remove(2); }
4. 空间分析模块
缓冲区分析
缓冲区分析实现的是对当前地图工作空间内的文档进行选定区图层的缓冲区分析,将分析产生的图层保存到指定路径。
添加缓冲区分析菜单项。双击菜单项添加响应函数:
IHookHelper map_hookHelper = new HookHelperClass(); map_hookHelper.Hook = this.axMapControl1.Object
BufferAnalysisForm BAFrm = new BufferAnalysisForm(map_hookHelper); BAFrm.ShowDialog();
新建Windows窗体
代码如下: using System;
using System.Drawing; using System.Text;
using System.Windows.Forms;
34