原文:《ArcGIS Engine+C#实例开发教程》第八讲 属性数据表的查询显示

在上一讲中,我们完成了图层符号选择器的制作。这一讲中,我们将实现图层属性数据表的查询显示。

在ArcMap中,单击图层右键菜单中的“Open Attribute Table”命令,便可弹出属性数据表。本讲将完成类似的功能,效果如下:

图1

数据表显示,我们用了DataGridView控件。DataGridView控件提供一种强大而灵活的以表格形式显示数据的方式。可以使用 DataGridView控件来显示少量数据的只读视图,也可以对其进行缩放以显示特大数据集的可编辑视图。我们可以很方便地把一个DataTable作为数据源绑定到DataGridView控件中。

本讲的思路大体如下:首先根据图层属性中的字段创建一个空的DataTable,然后根据数据内容一行行填充DataTable数据,再将DataTable绑定到DataGridView控件,最后调用并显示属性表窗体。

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。实现函数如下:

/// <summary>

/// 根据图层字段创建一个只含字段的空DataTable

/// </summary>

/// <param name="pLayer"></param>

/// <param name="tableName"></param>

/// <returns></returns>

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)

{

pDataColumn.Unique = true;//字段值是否唯一

}

//字段值是否允许为空

pDataColumn.AllowDBNull = pField.IsNullable;

//字段别名

pDataColumn.Caption = pField.AliasName;

//字段数据类型

pDataColumn.DataType = System.Type.GetType(ParseFieldType(pField.Type));

//字段默认值

pDataColumn.DefaultValue = pField.DefaultValue;

//当字段为String类型是设置字段长度

if (pField.VarType == 8)

{

pDataColumn.MaxLength = pField.Length;

}

//字段添加到表中

pDataTable.Columns.Add(pDataColumn);

pField = null;

pDataColumn = null;

}

return pDataTable;

}

因为GeoDatabase的数据类型与.NET的数据类型不同,故要进行转换。转换函数如下:

/// <summary>

/// 将GeoDatabase字段类型转换成.Net相应的数据类型

/// </summary>

/// <param name="fieldType">字段类型</param>

/// <returns></returns>

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";

}

}

摘要:这一讲中,我们将实现图层属性数据表的查询显示。在ArcMap中,单击图层右键菜单中的“Open Attribute Table”命令,便可弹出属性数据表。本讲将完成类似的功能.

3.装载DataTable数据

从上一步得到的DataTable还没有数据,只有字段信息。因此,我们要通过ICursor从ITable中逐一取出每一行数据,即IRow。再创建DataTable中相应的DataRow,根据IRow设置DataRow信息,再将所有的DataRow添加到DataTable中,就完成了DataTable数据的装载。

为保证效率,一次最多只装载2000条数据到DataGridView。函数代码如下:

 /// <summary>

/// 填充DataTable中的数据

/// </summary>

/// <param name="pLayer"></param>

/// <param name="tableName"></param>

/// <returns></returns>

public static DataTable CreateDataTable(ILayer pLayer, string tableName)

{

//创建空DataTable

DataTable pDataTable = CreateDataTableByLayer(pLayer, tableName);

//取得图层类型

string shapeType = getShapeType(pLayer);

//创建DataTable的行对象

DataRow pDataRow = null;

//从ILayer查询到ITable

ITable pTable = pLayer as ITable;

ICursor pCursor = pTable.Search(null, false);

//取得ITable中的行信息

IRow pRow = pCursor.NextRow();

int n = 0;

while (pRow != null)

{

//新建DataTable的行对象

pDataRow = pDataTable.NewRow();

for (int i = 0; i < pRow.Fields.FieldCount; i++)

{

//如果字段类型为esriFieldTypeGeometry,则根据图层类型设置字段值

if (pRow.Fields.get_Field(i).Type == esriFieldType.esriFieldTypeGeometry)

{

pDataRow[i] = shapeType;

}

//当图层类型为Anotation时,要素类中会有esriFieldTypeBlob类型的数据,

//其存储的是标注内容,如此情况需将对应的字段值设置为Element

else if (pRow.Fields.get_Field(i).Type == esriFieldType.esriFieldTypeBlob)

{

pDataRow[i] = "Element";

}

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判断图层类型的,代码如下:

/// <summary>

/// 获得图层的Shape类型

/// </summary>

/// <param name="pLayer">图层</param>

/// <returns></returns>

public static string getShapeType(ILayer pLayer)

{

IFeatureLayer pFeatLyr = (IFeatureLayer)pLayer;

switch (pFeatLyr.FeatureClass.ShapeType)

{

case esriGeometryType.esriGeometryPoint:

return "Point";

case esriGeometryType.esriGeometryPolyline:

return "Polyline";

case esriGeometryType.esriGeometryPolygon:

return "Polygon";

default:

return "";

}

}

4.绑定DataTable到DataGridView

通过以上步骤,我们已经得到了一个含有图层属性数据的DataTable。现定义一个AttributeTableFrm类的成员变量:

 public DataTable attributeTable;

通过以下函数,我们很容易将其绑定到DataGridView控件中。

 /// <summary>

/// 绑定DataTable到DataGridView

/// </summary>

/// <param name="player"></param>

public void CreateAttributeTable(ILayer player)

{

string tableName;

tableName = getValidFeatureClassName(player .Name );

attributeTable = CreateDataTable(player,tableName );

this.dataGridView1 .DataSource = attributeTable ;

this.Text = "属性表[" + tableName + "] " + "记录数:"+attributeTable.Rows.Count .ToString();

}

因为DataTable的表名不允许含有“.”,因此我们用“_”替换。函数如下:

/// <summary>

/// 替换数据表名中的点

/// </summary>

/// <param name="FCname"></param>

/// <returns></returns>

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)

{

//

// TODO: Define values for the public properties

//

base.m_category = ""; //localizable text

base.m_caption = "打开属性表"; //localizable text

base.m_message = "打开属性表"; //localizable text

base.m_toolTip = "打开属性表"; //localizable text

base.m_name = "打开属性表"; //unique id, non-localizable (e.g. "MyCategory_MyCommand")

m_pLayer = pLayer;

try

{

//

// TODO: change bitmap name if necessary

//

string bitmapResourceName = GetType().Name + ".bmp";

base.m_bitmap = new Bitmap(GetType(), bitmapResourceName);

}

catch (Exception ex)

{

System.Diagnostics.Trace.WriteLine(ex.Message, "Invalid Bitmap");

}

}

再在On_Click函数中添加如下代码,以创建并打开属性表窗体。

 /// <summary>

/// Occurs when this command is clicked

/// </summary>

public override void OnClick()

{

// TODO: Add OpenAttributeTable.OnClick implementation

AttributeTableFrm attributeTable = new AttributeTableFrm();

attributeTable.CreateAttributeTable(m_pLayer);

attributeTable.ShowDialog();

}

至此,我们完成了OpenAttributeTable命令。显然,我们要在TOCControl的OnMouseDown事件中调用此命令。

因为,当前选中的图层参数,即ILayer是通过OpenAttributeTable的构造函数传入的,而选中的ILayer是动态变化的,所以我们无法在窗体初始化的Form1_Load事件中就添加OpenAttributeTable菜单项到右键菜单。但我们可以在OnMouseDown事件中动态添加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)

{

//动态添加OpenAttributeTable菜单项

m_menuLayer.AddItem(new OpenAttributeTable(layer), -1, 2, true, esriCommandStyles.esriCommandStyleTextOnly);

m_menuLayer.PopupMenu(e.x, e.y, m_tocControl.hWnd);

//移除OpenAttributeTable菜单项,以防止重复添加

m_menuLayer.Remove(2);

}

}

6.编译运行

按下F5,编译运行程序,相信你已经实现了开篇处展示的属性表效果了吧!

以上代码在Windows XP Sp3 + VS2005 + AE9.2环境下编译通过。

《ArcGIS Engine+C#实例开发教程》第八讲 属性数据表的查询显示的更多相关文章

  1. 《ArcGIS Engine+C#实例开发教程》第二讲 菜单的添加及其实现

    原文:<ArcGIS Engine+C#实例开发教程>第二讲 菜单的添加及其实现 摘要:在上一讲中,我们实现了应用程序基本框架,其中有个小错误,在此先跟大家说明下.在“属性”选项卡中,我们 ...

  2. 《ArcGIS Engine+C#实例开发教程》第一讲桌面GIS应用程序框架的建立

    原文:<ArcGIS Engine+C#实例开发教程>第一讲桌面GIS应用程序框架的建立 摘要:本讲主要是使用MapControl.PageLayoutControl.ToolbarCon ...

  3. 《ArcGIS Engine+C#实例开发教程》第七讲 图层符号选择器的实现2

    原文:<ArcGIS Engine+C#实例开发教程>第七讲 图层符号选择器的实现2 摘要:在第七讲 图层符号选择器的实现的第一阶段中,我们完成了符号选择器窗体的创建与调用.在第二阶段中, ...

  4. 《ArcGIS Engine+C#实例开发教程》第六讲 右键菜单添加与实现

    原文:<ArcGIS Engine+C#实例开发教程>第六讲 右键菜单添加与实现 摘要:在这一讲中,大家将实现TOCControl控件和主地图控件的右键菜单.在AE开发中,右键菜单有两种实 ...

  5. 《ArcGIS Engine+C#实例开发教程》第四讲 状态栏信息的添加与实现

    原文:<ArcGIS Engine+C#实例开发教程>第四讲 状态栏信息的添加与实现 摘要:在上一讲中,我们完成了 MapControl 和PageLayoutControl两种视图的同步 ...

  6. 《ArcGIS Engine+C#实例开发教程》第五讲 鹰眼的实现

    原文:<ArcGIS Engine+C#实例开发教程>第五讲 鹰眼的实现 摘要:所谓的鹰眼,就是一个缩略地图,上面有一个矩形框,矩形框区域就是当前显示的地图区域,拖动矩形框可以改变当前地图 ...

  7. 《ArcGIS Engine+C#实例开发教程》第三讲 MapControl与PageLayoutControl同步

    原文:<ArcGIS Engine+C#实例开发教程>第三讲 MapControl与PageLayoutControl同步 摘要:在ArcMap中,能够很方面地进行MapView和Layo ...

  8. 《ArcGIS Engine+C#实例开发教程》

    原文:<ArcGIS Engine+C#实例开发教程> 摘要:<ArcGIS Engine+C#实例开发教程>,面向 ArcGIS Engine(以下简称AE)开发初学者,本教 ...

  9. ArcGIS Runtime for Android开发教程V2.0(1)基本概念

    原文地址: ArcGIS Runtime for Android开发教程V2.0(1)基本概念 - ArcGIS_Mobile的专栏 - 博客频道 - CSDN.NET http://blog.csd ...

随机推荐

  1. 对象创建型模式------Abstract Factory(抽象工厂)

    1. 意图    提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类.2. 别名    Kit3. 动机        假设我们要开发一款游戏,当然为了吸引更多的人玩,游戏难度不能太大 ...

  2. Scala语言初识

    scala是一种集面向对象特性和函数式特性于一身并可运行在JVM上的强类型静态语言.因为可以运行在JVM上,并在设计时借鉴于大量的java语言特性,故可以和java互动并可以调用java相关类库,这让 ...

  3. C# ACM poj1006

    中国剩余定理 public static void acm1006(int a, int b, int c, int d) { * ; * ; * ; * * ; ) * z; ) * y; ) * ...

  4. CruiseControl.NET : Configuration Preprocessor

    Original link: http://build.sharpdevelop.net/ccnet/doc/CCNET/Configuration%20Preprocessor.html http: ...

  5. 九度OJ 1499 项目安排 -- 动态规划

    题目地址:http://ac.jobdu.com/problem.php?pid=1499 题目描述: 小明每天都在开源社区上做项目,假设每天他都有很多项目可以选,其中每个项目都有一个开始时间和截止时 ...

  6. NSSpeechSynthesizer 文字变语音

    NSSpeechSynthesizer 是AVFoundation中的一个类,这个类可以方便的在Cocoa应用程序中添加"文本到语言"功能.开发者可以使用这个类向iOS 引用程序中 ...

  7. JS验证邮箱格式是否正确的代码

    验证邮箱格式是否正确的方法有很多,接下来为大家介绍下使用js是如何做到的 复制代码代码如下: /*  *验证邮箱格式是否正确  *参数strEmail,需要验证的邮箱  */ www.jbxue.co ...

  8. CSS实现文字上标、下标

    .sup{vertical-align:super; color:red; font-size:9px; font-family:Arial, Helvetica, sans-serif; margi ...

  9. jQuery的基本信息。以及入门Demo

    javascript目前最流行的框架jQuery,它是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器.jQuery的作者的核心理念就是write less,do more(写得更少,做得更多).他 ...

  10. ECSHOP 订单状态 记录

    记录订单状态 order_status /* 订单状态 */ define(‘OS_UNCONFIRMED’,            0); // 未确认 define(‘OS_CONFIRMED’, ...