logo资料库

ArcGIS engine 显示属性表.docx

第1页 / 共7页
第2页 / 共7页
第3页 / 共7页
第4页 / 共7页
第5页 / 共7页
第6页 / 共7页
第7页 / 共7页
资料共7页,全文预览结束
ArcGIS Engine+C#_属性数据表的查询显示 2012 年 06 月 19 日 星期二 14:33 本讲的思路大体如下:首先根据图层属性中的字段创建一个空的 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。实现函数如下: /// /// 根据图层字段创建一个只含字段的空 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) { 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 的数据类型不同,故要进行转换。转换函数如下: /// /// 将 GeoDatabase 字段类型转换成.Net 相应的数据类型 /// /// 字段类型 /// 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"; } } 3.装载 DataTable 数据 从上一步得到的 DataTable 还没有数据,只有字段信息。因此,我们要通过 ICursor 从 ITable 中逐一取出每一行数据,即 IRow。再创建 DataTable 中相应的 DataRow,根据 IRow 设置 DataRow 信息,再将所有的 DataRow 添加到 DataTable 中,就完成了 DataTable 数据的装载。 为保证效率,一次最多只装载 2000 条数据到 DataGridView。函数代码如下: /// /// 填充 DataTable 中的数据 /// /// /// /// 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 判断图 层类型的,代码如下: /// /// 获得图层的 Shape 类型 /// /// 图层 /// 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 控件中。
/// /// 绑定 DataTable 到 DataGridView /// /// 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 的表名不允许含有“.”,因此我们用“_”替换。函数如下: /// /// 替换数据表名中的点 /// /// /// 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 函数中添加如下代码,以创建并打开属性表窗体。 /// /// Occurs when this command is clicked /// 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); } }
分享到:
收藏