In ArcMap, right-click the "Open Attribute Table" command in the layer menu to bring up the Attribute data Table. This document describes how to implement the following functions:
Figure 1
The data table shows that the DataGridView control is used. The DataGridView control provides a powerful and flexible way to display data in tables. You can use the DataGridView control to display a read-only view of a small amount of data, or scale it to display an editable view of a super large dataset. We can easily bind a able as a data source to the DataGridView control.
The general idea of this article is as follows: first, create an empty DataTable Based on the fields in the layer attribute, then fill in the DataTable data based on a row of data content, and then bind the DataTable to the DataGridView control, finally, call and display the Attribute Table form.
1. Create an Attribute Table form
Create a new Windows form named AttributeTableFrm. cs ".
Drag a dview control from the toolbox to the form, and set its Dock attribute to "Fill ". // Fill it with the entire form
Add the following reference:
Using ESRI. ArcGIS. Carto;
Using ESRI. ArcGIS. Controls;
Using ESRI. ArcGIS. esriSystem;
Using ESRI. ArcGIS. SystemUI;
Using ESRI. ArcGIS. Geometry;
Using ESRI. ArcGIS. Geodatabase;
Add reference
2. Create an empty DataTable
First pass in ILayer, then query ITable, get each Field from Fileds in ITable, then set DataColumn of DataTable Based on Filed, and then create an empty DataTable with only layer fields. The implementation functions are as follows:
/// <Summary>
/// Create an empty able containing only fields based on the layer field
/// </Summary>
/// <Param name = "pLayer"> </param>
/// <Param name = "tableName"> </param>
/// <Returns> </returns>
Private static DataTable CreateDataTableByLayer (ILayer pLayer, string tableName)
{
// Create a able table
DataTable pDataTable = new DataTable (tableName );
// Obtain the ITable Interface
ITable pTable = pLayer as ITable;
IField pField = null;
DataColumn pDataColumn; // columns in System. Data. able
// Create a DataColumn object based on the attributes of each field
For (int I = 0; I <pTable. Fields. FieldCount; I ++)
{
PField = pTable. Fields. get_Field (I );
// Create a DataColumn and set its attributes
PDataColumn = new DataColumn (pField. Name );
If (pField. Name = pTable. OIDFieldName) // each row in this column must be unique
{
PDataColumn. Unique = true; // whether the field value is Unique
}
// Whether the field value can be blank
PDataColumn. AllowDBNull = pField. IsNullable;
// Field alias
PDataColumn. Caption = pField. AliasName;
// Field Data Type
PDataColumn. DataType = System. Type. GetType (ParseFieldType (pField. Type ));
// Default Field Value
PDataColumn. DefaultValue = pField. DefaultValue;
// When the field is of the String type, the field length is set.
If (pField. VarType = 8)
{
PDataColumn. MaxLength = pField. Length;
}
// Add fields to the table
PDataTable. Columns. Add (pDataColumn );
PField = null;
PDataColumn = null;
}
Return pDataTable;
}
Conversion is required because the data type of GeoDatabase is different from that of. NET. The conversion function is as follows:
/// <Summary>
/// Convert the GeoDatabase field type to the. Net data type
/// </Summary>
/// <Param name = "fieldType"> Field Type </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 ";
}
}
3. Load DataTable data
The DataTable obtained from the previous step has no data and only field information. Therefore, we need to use ICursor to extract each row of data from ITable one by one, that is, IRow. Create the corresponding DataRow in the able, set the DataRow information according to the IRow, and add all DataRow to the DataTable to load the DataTable data.
To ensure efficiency, a maximum of 2000 data entries can be loaded to the dview at a time. The function code is as follows:
/// <Summary>
/// Fill in the data in the DataTable
/// </Summary>
/// <Param name = "pLayer"> </param>
/// <Param name = "tableName"> </param>
/// <Returns> </returns>
Public static DataTable CreateDataTable (ILayer pLayer, string tableName)
{
// Create an empty DataTable
DataTable pDataTable = CreateDataTableByLayer (pLayer, tableName );
// Obtain the layer type
String shapeType = getShapeType (pLayer );
// Create the row object of the DataTable
DataRow pDataRow = null;
// Query ITable from ILayer
ITable pTable = pLayer as ITable;
ICursor pCursor = pTable. Search (null, false );
// Obtain the row information in ITable
IRow pRow = pCursor. NextRow ();
Int n = 0;
While (pRow! = Null)
{
// Create a row object for the DataTable
PDataRow = pDataTable. NewRow ();
For (int I = 0; I <pRow. Fields. FieldCount; I ++)
{
// If the field type is esriFieldTypeGeometry, set the field value based on the layer type.
If (pRow. Fields. get_Field (I). Type = esriFieldType. esriFieldTypeGeometry)
{
PDataRow [I] = shapeType;
}
// When the layer type is Anotation, esriFieldTypeBlob data is contained in the element class,
// It stores the annotation content. In this case, set the corresponding field value to Element.
Else if (pRow. Fields. get_Field (I). Type = esriFieldType. esriFieldTypeBlob)
{
PDataRow [I] = "Element ";
}
Else
{
PDataRow [I] = pRow. get_Value (I );
}
}
// Add DataRow to DataTable
PDataTable. Rows. Add (pDataRow );
PDataRow = null;
N ++;
// To ensure efficiency, only a maximum of records can be loaded at a time
If (n = 2000)
{
PRow = null;
}
Else
{
PRow = pCursor. NextRow ();
}
}
Return pDataTable;
}
The above Code involves a function getShapeTape to obtain the layer type. This function uses ILayer to determine the layer type. The Code is as follows:
/// <Summary>
/// Obtain the Shape type of the layer
/// </Summary>
/// <Param name = "pLayer"> layer </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. Bind The DataTable to the DataGridView
Through the above steps, we have obtained a DataTable containing layer attribute data. A AttributeTableFrm class member variable is defined:
Public DataTable attributeTable;
Using the following functions, we can easily bind them to the dview control.
/// <Summary>
/// Bind the DataTable to the 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 = "Attribute Table [" + tableName + "]" + "number of records:" + attributeTable. Rows. Count. ToString ();
}
Because the DataTable table name cannot contain ".", we use "_" instead. The function is as follows:
/// <Summary>
/// Replace the vertex in the data table name
/// </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. Call the Attribute Table form
Step 1-4 encapsulates an AttributeTableFrm class that can display Attribute Table data in layers by ILayer. How can we call AttributeTableFrm?
As mentioned above, the attribute table form is displayed in the context menu of the selected Layer in TOCControl. Therefore, we need to add a menu item to the context menu of the Layer in TOCControl. In the sixth lecture, we use the IToolbarMenu in AE to implement the right-click menu. Therefore, we need to customize a Command to enable the Attribute Table function.
Create an item "OpenAttributeTable. cs" using Base Command of ArcGIS as the template ".
Note: When creating a Base Command template, a dialog box will pop up asking us to select the target object of the template. In this case, select MapControl and PageLayoutControl, that is, select the second or second to last.
Add the following reference:
Using ESRI. ArcGIS. Carto;
Using ESRI. ArcGIS. Display;
Using ESRI. ArcGIS. esriSystem;
Add member variables:
Private ILayer m_pLayer;
Modify the constructor:
Public OpenAttributeTable (ILayer pLayer)
{
//
// TODO: Define values for the public properties
//
Base. m_category = ""; // localizable text
Base. m_caption = "Open Attribute Table"; // localizable text
Base. m_message = "Open Attribute Table"; // localizable text
Base. m_toolTip = "Open Attribute Table"; // localizable text
Base. m_name = "Open Attribute Table"; // 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 ");
}
}
Add the following code to the On_Click function to create and open the Attribute Table form.
/// <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 ();
}
So far, we have completed the OpenAttributeTable command. Obviously, we need to call this command in the OnMouseDown event of TOCControl.
Because the currently selected layer parameter, that is, ILayer is passed in through the OpenAttributeTable constructor, and the selected ILayer is dynamically changed, therefore, you cannot add the OpenAttributeTable menu item to the right-click menu in the Form1_Load event of form initialization. However, we can dynamically add OpenAttributeTable menu items in the OnMouseDown event.
Note that the added OpenAttributeTable menu item must be removed. Otherwise, this menu item will be added each time you right-click it, which will contain multiple OpenAttributeTable menu items.
The code for modifying the OnMouseDown event of TOCControl is as follows:
Private void axtoccontrolpoliconmousedown (object sender, ITOCControlEvents_OnMouseDownEvent e)
{
//......
// Right-click the menu
If (item = esriTOCControlItem. esriTOCControlItemMap)
M_menuMap.PopupMenu (e. x, e. y, m_tocControl.hWnd );
If (item = esriTOCControlItem. esriTOCControlItemLayer)
{
// Dynamically add OpenAttributeTable menu items
M_menuLayer.AddItem (new OpenAttributeTable (layer),-1, 2, true, esriCommandStyles. esriCommandStyleTextOnly );
M_menuLayer.PopupMenu (e. x, e. y, m_tocControl.hWnd );
// Remove the OpenAttributeTable menu item to prevent repeated addition
M_menuLayer.Remove (2 );
}
}
6. Compile and run
This article from the CSDN blog, reproduced please indicate the source: http://blog.csdn.net/Terminatorss/archive/2009/08/01/4400238.aspx