ArcEngine入门开发第4篇:属性表的常用操作

内容摘要:

本文提供利用ArcEngine10.7&VS2017设计Windows窗体实现对Mxd地图文档属性表的常用操作,显示图层属性,包括查看属性表+删除图层,同时解决“未找到类型或命名空间名”等问题的报错,往期文章:

ArcEngine入门开发第1篇:ArcEngine10.7&VS2017环境配置

ArcEngine入门开发第2篇:打开/保存Mxd地图文档

ArcEngine入门开发第3篇:距离/面积量算

本文内容接上篇。

一、开发环境

1.语言:C#

2.编程环境:Visual Studio2017

3.ArcEngine版本:10.7

二、菜单栏设计

在“工具箱”中选择“菜单和工具栏”中的“ContextMenuStrip”控件,双击该控件,将其添加至Form1窗体中,输入两个选项“查看属性表”和“删除该图层”。

dcf2db6f028e49cb9d01640c7e279bac.png

cc3ee5bd3ce7454bb9917c4a6ccfb75b.png

点击Form1窗体中的TOCControl控件,在右端显示的属性窗口中选择其ContextMenuStrip属性为contextMenuStrip1,表示将该控件和我们刚刚添加的ContextMenuStrip控件进行绑定,在此基础上添加事件代码(后文会提到),右键TOCControl上的图层时会显示查看属性表和删除该图层的选项。

6198d7dd45694cef878f63288f03b36f.png

三、AttributesTable窗体设计

在解决方案资源管理器中右键该项目,选择添加→Windows窗体,将窗体名称设置为AttributesTable.cs,点击“添加”按钮,该窗体用于显示图层的属性表。

b05f3320d99b473ab913c000197a7036.png

902b41ef2dcf424cb07a1d5d1ecd09e4.png

为AttributesTable窗体添加控件,在工具箱的公共控件中找到“Label”控件,将其拖动至窗体左上角位置,该控件用于显示属性表名称。在工具箱中搜索“data”,显示如图所示的“DataGridView”控件,将其拖动到窗体中,在属性窗口中将其Dock属性设置为Bottom,拉长控件使其充满整个窗体。

69714c40b45d415f81bf99a186422dd0.png

3249b0a0394d4b2f8c094943538d88c5.png

d639dc6b3252468e91db05d6309a073e.png

接下来双击AttributesTable窗体添加代码,在 public partial class Form1 : Form内添加所需变量:

 string name;
        public ILayer Layer;
        public IFeatureLayer pFeatureLayer;
        AxMapControl axMapControl;
        IMap pMap;
        ILayer layer;

本节添加代码后系统会显示很多错误提示,在后文我们会逐一解决。

将原构造函数修改为如下代码:

public AttributesTable(IFeatureLayer pGlobalFeatureLayer, AxMapControl axMapControl1)
        {
            InitializeComponent();
            //窗体出现位置
            this.StartPosition = FormStartPosition.Manual;
            this.Location = new System.Drawing.Point(this.Left = 700, this.Top = 24);
            pFeatureLayer = pGlobalFeatureLayer;
            axMapControl = axMapControl1;
            pMap = axMapControl.Map;
        }

在如下函数中添加代码:

private void AttributesTable_Load(object sender, EventArgs e)
        {
            Itable2Dtable(pFeatureLayer);
        }

public partial class Form1 : Form中实现Itable2Dtable函数:

public void Itable2Dtable(IFeatureLayer pFeatureLayer)
        {
            if (pFeatureLayer != null && pFeatureLayer.FeatureClass != null)
            {
                label1.Text = pFeatureLayer.Name.ToString() + "的属性表";
                name = pFeatureLayer.Name.ToString();

                IFields pFields = pFeatureLayer.FeatureClass.Fields;

                // 设置 DataGridView 的列数和列标题
                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(ParseFieldType(pFields.get_Field(i).Type));
                }

                // 使用 FeatureCursor 获取特征
                IFeatureCursor pFeatureCursor = pFeatureLayer.FeatureClass.Search(null, false);
                IFeature pFeature;

                // 处理每一个特征
                while ((pFeature = pFeatureCursor.NextFeature()) != null)
                {
                    string[] fldValue = new string[pFields.FieldCount];

                    // 获取特征的每一个字段值
                    for (int i = 0; i < pFields.FieldCount; i++)
                    {
                        string 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));
                        }
                    }

                    // 将字段值添加到 DataGridView 的行中
                    dataGridView1.Rows.Add(fldValue);
                }
            }
            else
            {
                // 处理 pFeatureLayer 或者 pFeatureLayer.FeatureClass 为空的情况
                MessageBox.Show("Feature layer or its feature class is null.");
            }
        }

在Itable2Dtable函数中调用了ParseFieldType函数,因此需要在public partial class Form1 : Form中实现ParseFieldType函数:

public static string ParseFieldType(esriFieldType fieldType)
        {
            switch (fieldType)
            {
                case esriFieldType.esriFieldTypeBlob:
                    return "System String";
                case esriFieldType.esriFieldTypeDate:
                    return "System DataTime";
                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";
            }

        }

设置dataGridView1的RowHeaderMouseClick事件,该事件表示用户在行标题边界内部单击时发生。返回AttributesTable窗体,点击DataGridView控件,在其属性窗口中点击第四个图标⚡,显示事件,点击第二个图标按字母排序,找到“RowHeaderMouseClick”事件,双击该事件进入AttributesTable.cs。

51cc5ff640e74fd4ba9c828c4dbfda65.png

在dataGridView1的RowHeaderMouseClick事件中添加如下代码:

private void dataGridView1_RowHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            IQueryFilter pQuery = new QueryFilter();
            IFeatureCursor pFeatCursor;
            pMap.ClearSelection();
            int count = this.dataGridView1.SelectedRows.Count;
            string val;
            string col;
            col = this.dataGridView1.Columns[0].Name;
            if (count == 1)
            {
                val = this.dataGridView1.SelectedRows[0].Cells[col].Value.ToString();
                pQuery.WhereClause = col + "=" + val;
            }
            else
            {
                int i;
                string str;
                for (i = 0; i < count - 1; i++)
                {
                    val = this.dataGridView1.SelectedRows[i].Cells[col].Value.ToString();
                    str = col + "= " + val + "OR";
                    pQuery.WhereClause += str;
                }

                val = this.dataGridView1.SelectedRows[0].Cells[col].Value.ToString();
                str = col + "" + val;
                pQuery.WhereClause += str;
            }

            try
            {
                ZoomToSelectedFeature(pFeatureLayer, pQuery);
                pFeatCursor = pFeatureLayer.Search(pQuery, true);
                IFeatureClass fcls = pFeatureLayer.FeatureClass;
                IFeatureCursor featureCursor = fcls.Search(pQuery, true);
                FlashPolygons(featureCursor);

            }
            catch (Exception ex)
            {
                MessageBox.Show("有错误");
            }
        }

public partial class Form1 : Form中实现GetRGB函数获取颜色:

private IRgbColor GetRGB(int r, int g, int b)
        {
            IRgbColor pColor;
            pColor = new RgbColor();
            pColor.Red = r;
            pColor.Green = g;
            pColor.Blue = b;
            return pColor;
        }

public partial class Form1 : Form中实现FlashPolygons函数使得选中要素闪烁:

private void FlashPolygons(IFeatureCursor featureCursor)
        {
            IArray geoArray = new ESRI.ArcGIS.esriSystem.Array();
            IFeature feature = null;
            while ((feature = featureCursor.NextFeature()) != null)
            {
                geoArray.Add(feature.ShapeCopy);
            }
            HookHelper m_pHookHelper = new HookHelper();
            m_pHookHelper.Hook = axMapControl.Object;
            IHookActions hookActions = (IHookActions)m_pHookHelper;
            hookActions.DoActionOnMultiple(geoArray, esriHookActions.esriHookActionsPan);
            Application.DoEvents();
            m_pHookHelper.ActiveView.ScreenDisplay.UpdateWindow();
            hookActions.DoActionOnMultiple(geoArray, esriHookActions.esriHookActionsFlash);
        }

 在public partial class Form1 : Form中实现ZoomToSelectedFeature函数进行视图转换:

        private void ZoomToSelectedFeature(IFeatureLayer pFeatureLyr, IQueryFilter pQueryFilter)
        {
            IFeatureSelection pFeatSelection;
            ISimpleMarkerSymbol pMarkerSymbol;
            ISimpleLineSymbol pLineSymbol;
            ISimpleFillSymbol pFillSymb;
            IFeatureLayer pLayer;
            IFeatureClass pFeatureCls;
            for (int i = 0; i < axMapControl.LayerCount; i++)
            {
                ILayer lyr = axMapControl.Map.get_Layer(i);
                if (lyr.Name == name)
                {
                    layer = lyr;
                    pLayer = (IFeatureLayer)layer;
                    pFeatureCls = pLayer.FeatureClass;
                    switch (pFeatureCls.ShapeType)
                    {
                        case esriGeometryType.esriGeometryPoint:
                            pMarkerSymbol = new SimpleMarkerSymbol();
                            pMarkerSymbol.Style = esriSimpleMarkerStyle.esriSMSCircle;
                            pMarkerSymbol.Color = GetRGB(0, 255, 255);
                            pMarkerSymbol.Angle = 30;
                            pMarkerSymbol.Size = 5;
                            pMarkerSymbol.Outline = true;
                            pMarkerSymbol.OutlineSize = 1;
                            pMarkerSymbol.OutlineColor = GetRGB(50, 50, 50);
                            pFeatSelection = (IFeatureSelection)layer;
                            pFeatSelection.SelectFeatures(pQueryFilter, esriSelectionResultEnum.esriSelectionResultNew, false);
                            pFeatSelection.SetSelectionSymbol = true;
                            pFeatSelection.SelectionSymbol = (ISymbol)pMarkerSymbol;
                            ISelectionSet pSelectionSet = pFeatSelection.SelectionSet;
                            IEnumGeometry pEnumGeom = new EnumFeatureGeometry();
                            IEnumGeometryBind pEnumGeomBind = pEnumGeom as IEnumGeometryBind;
                            pEnumGeomBind.BindGeometrySource(null, pSelectionSet);
                            IGeometryFactory pGeomFactory = new GeometryEnvironmentClass();
                            IGeometry pGeom = pGeomFactory.CreateGeometryFromEnumerator(pEnumGeom);
                            axMapControl.ActiveView.Extent = pGeom.Envelope;
                            axMapControl.ActiveView.Refresh();
                            break;
                        case esriGeometryType.esriGeometryPolyline:
                            pLineSymbol = new SimpleLineSymbol();
                            pLineSymbol.Style = esriSimpleLineStyle.esriSLSDot; pLineSymbol.Color = GetRGB(0, 255, 255);
                            pLineSymbol.Width = 3;
                            pFeatSelection = (IFeatureSelection)layer;
                            pFeatSelection.SelectFeatures(pQueryFilter, esriSelectionResultEnum.esriSelectionResultNew, false);
                            pFeatSelection.SetSelectionSymbol = true;
                            pFeatSelection.SelectionSymbol = (ISymbol)pLineSymbol;
                            ISelectionSet pSelectionSet1 = pFeatSelection.SelectionSet;
                            IEnumGeometry pEnumGeom1 = new EnumFeatureGeometry();
                            IEnumGeometryBind pEnumGeomBind1 = pEnumGeom1 as IEnumGeometryBind;
                            pEnumGeomBind1.BindGeometrySource(null, pSelectionSet1);
                            IGeometryFactory pGeomFactory1 = new GeometryEnvironmentClass();
                            IGeometry pGeom1 = pGeomFactory1.CreateGeometryFromEnumerator(pEnumGeom1);
                            axMapControl.ActiveView.Extent = pGeom1.Envelope;
                            axMapControl.ActiveView.Refresh();
                            break;
                        case esriGeometryType.esriGeometryPolygon:
                            pFillSymb = new SimpleFillSymbol();
                            pFillSymb.Color = GetRGB(0, 25, 255);
                            pFillSymb.Style = esriSimpleFillStyle.esriSFSSolid;
                            pFeatSelection = (IFeatureSelection)layer;
                            pFeatSelection.SelectFeatures(pQueryFilter, esriSelectionResultEnum.esriSelectionResultNew, false);
                            pFeatSelection.SetSelectionSymbol = true;
                            pFeatSelection.SelectionSymbol = (ISymbol)pFillSymb;
                            ISelectionSet pSelectionSet2 = pFeatSelection.SelectionSet;
                            IEnumGeometry pEnumGeom2 = new EnumFeatureGeometry();
                            IEnumGeometryBind pEnumGeomBind2 = pEnumGeom2 as IEnumGeometryBind;
                            pEnumGeomBind2.BindGeometrySource(null, pSelectionSet2);

                            IGeometryFactory pGeomFactory2 = new GeometryEnvironmentClass();
                            IGeometry pGeom2 = pGeomFactory2.CreateGeometryFromEnumerator(pEnumGeom2);
                            axMapControl.ActiveView.Extent = pGeom2.Envelope;
                            axMapControl.ActiveView.Refresh();
                            break;
                    }
                    break;
                }
            }
        }

此时AttributesTable窗体的全部函数添加完毕,此时系统会提示很多错误,这是由于缺少对部分ArcGIS指令的引用,莫慌!!在AttributesTable.cs中引用部分添加如下代码可解决部分问题:

79f40f98c11740aeb4366cda0cab8c15.png

using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Framework;
using ESRI.ArcGIS.ArcMapUI;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;

若仍然显示报错不存在类型或命名空间名,则右键解决方案资源管理器中“引用”,选择“添加引用”,在打开的引用管理器对话框中点击“扩展”,找到上述所有的引用并选中,点击“确定”按钮即可解决。

6fd225cc68bc4c7f87100601f788ef30.png

此时仍有错误提示如下。

89b7b5db967144818d7a269349c57324.png

在解决方案资源管理器中点击“引用”,找到“ESRI.ArcGIS.Geometry”引用,右键选择“属性”,在属性窗口中将其嵌入互操作类型设置为“False”即可解决。

424e830c75cd40e9a1da9ab6b52d2b95.png

四、Form1主窗体设计

点击回到Form1.cs[设计],在属性窗口的下拉框中找到contextMenuStrip1,点击该选项后窗体中显示设置过的ContextMenuStrip控件。

314c67352c0d4bcea0c9e580409c507c.png

 双击“查看属性表”按钮进入Form1.cs,在如下函数中添加代码,使得点击“查看属性表”时唤起AttributesTable窗体:

private void 查看属性表ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AttributesTable Ft = new AttributesTable(pGlobeLayer as IFeatureLayer, axMapControl1);
            Ft.Show();
        }

双击“删除该图层”按钮进入Form1.cs,在如下函数中添加代码:

private void 删除该图层ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (axMapControl1.LayerCount > 0)
            {
                if (pGlobeLayer != null)
                {
                    axMapControl1.Map.DeleteLayer(pGlobeLayer);
                }
            }
        }

此时错误提示如下。

2596b0eeb9f341f3a94d68314fde996b.png

 在public partial class Form1 : Form中添加如下变量声明即可解决:

private ILayer pGlobeLayer = null;

 最后一步,为TOCControl控件添加OnMouseDown事件的代码,在Form1窗体中点击TOCControl控件,在其属性窗口中点击第四个图标⚡,显示事件,点击第二个图标按字母排序,找到“OnMouseDown”事件,双击该事件进入Form1.cs。

 30332973cf8a46378a63bb4eca28045a.png

在如下函数中添加代码:

private void axTOCControl1_OnMouseDown(object sender, ESRI.ArcGIS.Controls.ITOCControlEvents_OnMouseDownEvent e)
        {
            if (axMapControl1.LayerCount > 0)
            {
                esriTOCControlItem pItem = new esriTOCControlItem();
                //pGlobeLayer为全局变量
                pGlobeLayer = new FeatureLayer();
                IBasicMap pBasicMap = new MapClass();
                object pOther = new object();
                object pIndex = new object();
                //获取点击的位置
                axTOCControl1.HitTest(e.x, e.y, ref pItem, ref pBasicMap, ref pGlobeLayer, ref pOther, ref pIndex);
                //点击的是Layer的话,则弹出上下文菜单
                if (e.button == 2 && pItem == esriTOCControlItem.esriTOCControlItemLayer)
                {
                    contextMenuStrip1.Show(axTOCControl1, e.x, e.y);
                }
            }
        }

此时系统显示错误提示如下。 

98cfa3cfee7c49e39dc8a88d2c8dffa3.png

这是由于缺少对部分ArcGIS指令的引用,在Form1.cs引用部分添加如下代码可解决:

using ESRI.ArcGIS.Controls;

若仍然显示报错不存在类型或命名空间名,则右键解决方案资源管理器中“引用”,选择“添加引用”,在打开的引用管理器对话框中点击“扩展”,找到“ESRI.ArcGIS.Controls”引用并选中,点击“确定”按钮即可解决。 

450211a906ab42f2ad264b8fc8b03b49.png

运行结果如下。

ce180333e6a9440ab1a40be390a325d4.png

选中属性表中的某一行会在地图上高亮显示该要素。 

16595b5952e541fb95a54188676f43a2.png

欢迎交流🌹🌹

  • 33
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值