ArcEngine做一个“仿”ArcMap中的属性表

1、需求

GIS的数据有空间信息和属性信息,基于ArcEngine开发GIS系统的时候,空间信息用MapControl可以直接展示,但是属性信息却没有相关的控件直接进行展示(或许有接口,我没有找到,而且arcobject自带的接口可能很难满足客户奇奇怪怪的需求)。参考ArcMap中的属性表的功能仿制了一个自定义控件。

2、界面设计

主界面设计

这个是自定义控件的主界面,有两个GridControl组成,之所以用两个GridControl,是为了避免在大量数据的情况下一个GridControl反复刷新造成卡顿。自定义控件的最下方是一个radio控件组和自定义分页控件(这个控件在之前的博文中有写:自定义分页控件)。另外,还支持全选、当前页面选择、取消选择、排序功能

3、代码实现

代码比较多,就按功能把核心代码贴上吧!

3.1 属性和私有变量定义

这里定义了一个私有事件,用来捕获地图选择集的改变。

        #region 定义事件
        private IActiveViewEvents_Event pActiveViewEvents;
        #endregion

        #region 定义属性
        public IMapControl4 BindingMapControl
        {
            get;private set;
        }

        /// <summary>
        /// 属性表页面标签,0表示所有属性表,1表示选择要素的属性表
        /// </summary>
        public int PageTag
        {
            get; private set;
        }

        /// <summary>
        /// 所有属性的表控件
        /// </summary>
        public GridControl AllDataGrid
        {
            get { return gridAllAttribute; }
        }

        /// <summary>
        /// 选择属性的表控件
        /// </summary>
        public GridControl SelectionDataGrid
        {
            get { return gridSelectAttribute; }
        }

        /// <summary>
        /// 所有属性的数据表
        /// </summary>
        public DataTable AllAttTable
        {
            get { return allRowsTable; }
        }

        /// <summary>
        /// 选择属性的数据表
        /// </summary>
        public DataTable SelectionAttTable
        {
            get { return selectionRowsTable; }
        }
        #endregion

        #region 私有变量定义
        private IQueryFilter queryFilter;
        private ISpatialFilter spatialFilter;
        private DataTable allRowsTable;
        private DataTable selectionRowsTable;
        private IFeatureLayer featureLayer;
        private List<int> selectIDList = new List<int>();
        private string oidFieldName;
        #endregion

3.2 控件初始化

大概思路是先创建含有属性字段的空表,再遍历每一个Feature填充表格,最后绑定到控件,其中,用一个临时的列表来存储选择的要素。这里的所有属性的表中还加了“选中要素”一列来标记选择的状态。注册ActiveViewEvents_SelectionChanged(地图选择集改变事件)

        public CtrlAttrubuteGrid(IMapControl4 pMapControl, ref IFeatureLayer pFeatureLayer, IQueryFilter pQueryFilter)
        {
            try
            {
                InitializeComponent();
                if (pFeatureLayer == null)
                {
                    return;
                }
                queryFilter = pQueryFilter;
                spatialFilter = pQueryFilter as ISpatialFilter;
                featureLayer = pFeatureLayer;
                oidFieldName = (featureLayer.FeatureClass as ITable).OIDFieldName;
                selectionRowsTable = GetSelectionRowsTable(featureLayer);
                allRowsTable = CteateCtrlAttributeTable(featureLayer);
                allRowsTable.DefaultView.Sort = oidFieldName + " ASC";
                allRowsTable = allRowsTable.DefaultView.ToTable();
                selectionRowsTable.DefaultView.Sort = oidFieldName + " ASC";
                selectionRowsTable = selectionRowsTable.DefaultView.ToTable();
                allRowsTable.PrimaryKey = new DataColumn[] { allRowsTable.Columns[oidFieldName] };
                selectionRowsTable.PrimaryKey = new DataColumn[] { selectionRowsTable.Columns[oidFieldName] };

                gridAllAttribute.DataSource = allRowsTable;
                gridSelectAttribute.DataSource = selectionRowsTable;
                gviewSelect.Columns[0].Visible = false;
                gridAllAttribute.Visible = true;
                gridAllAttribute.Dock = DockStyle.Fill;
                gridAllAttribute.Refresh();
                gridAllAttribute.RefreshDataSource();
                gridSelectAttribute.Visible = false;
                ctrlGridNavigation1.InitCtrl(allRowsTable, gridAllAttribute, new int[] { 50, 100, 500 });
                for (int i = 1; i < gviewAll.Columns.Count; i++)
                {
                    gviewAll.Columns[i].OptionsColumn.AllowEdit = false;
                }
                gviewAll.BestFitColumns();
                PageTag = 0;

                BindingMapControl = pMapControl;
                pActiveViewEvents = BindingMapControl.Map as IActiveViewEvents_Event;
                pActiveViewEvents.SelectionChanged += new IActiveViewEvents_SelectionChangedEventHandler(ActiveViewEvents_SelectionChanged);
            }
            catch (Exception ex)
            {
                XtraMessageBox.Show("属性表初始化失败");
            }
        }

        /// <summary>
        /// 获取要素图层中选择要素的属性表
        /// </summary>
        /// <param name="pFeatureLayer"></param>
        /// <returns></returns>
        private DataTable GetSelectionRowsTable(IFeatureLayer pFeatureLayer)
        {
            selectIDList = new List<int>();
            DataTable pDataTable = CreateDataTableByLayer(pFeatureLayer, pFeatureLayer.Name);
            using (ComReleaser comReleaser = new ComReleaser())
            {
                string oidFieldName = pFeatureLayer.FeatureClass.OIDFieldName;
                ICursor pCursor = null;
                DataRow pDataRow = null;
                comReleaser.ManageLifetime(pCursor);
                string shapeType = GetShapeType(pFeatureLayer);
                IFeatureSelection pFeatureSelection = featureLayer as IFeatureSelection;
                ISelectionSet pSelectionSet = pFeatureSelection.SelectionSet;
                if (pSelectionSet.Count == 0)
                    return pDataTable;
                pSelectionSet.Search(null, false, out pCursor);
                IRow pRow = pCursor.NextRow();
                comReleaser.ManageLifetime(pRow);
                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["Shape"] = shapeType;
                        }
                        //当图层类型为Anotation时,要素类中会有esriFieldTypeBlob类型的数据,
                        //其存储的是标注内容,如此情况需将对应的字段值设置为Element
                        else if (pRow.Fields.get_Field(i).Type == esriFieldType.esriFieldTypeBlob)
                        {
                            pDataRow[i] = "Element";
                        }
                        else
                        {
                            string o = pRow.get_Value(i).ToString();
                            pDataRow[pRow.Fields.Field[i].Name] = pRow.get_Value(i);
                        }
                    }
                    pDataRow[0] = true;
                    selectIDList.Add(Convert.ToInt32(pDataRow[oidFieldName]));
                    pDataTable.Rows.Add(pDataRow);
                    pDataRow = null;
                    n++;
                    pRow = pCursor.NextRow();
                }
            }
            return pDataTable;
        }


        /// <summary>
        /// 创建属性表
        /// </summary>
        /// <param name="_featureLayer">待创建属性表的要素图层</param>
        /// <returns>返回创建的字段表</returns>
        private DataTable CteateCtrlAttributeTable(IFeatureLayer _featureLayer)
        {
            DataTable pDataTable = CreateDataTableByLayer(_featureLayer, _featureLayer.Name);
            string shapeType = GetShapeType(_featureLayer);
            DataRow pDataRow = null;
            ITable pTable = _featureLayer as ITable;
            ICursor pCursor = pTable.Search(queryFilter, false);
            IRow pRow = pCursor.NextRow();
            int n = 0;
            while (pRow != null)
            {
                using (ComReleaser comReleaser = new ComReleaser())
                {
                    comReleaser.ManageLifetime(pRow);
                    //新建DataTable的行对象
                    pDataRow = pDataTable.NewRow();
                    for (int i = 0; i < pRow.Fields.FieldCount; i++)
                    {
                        //如果字段类型为esriFieldTypeGeometry,则根据图层类型设置字段值
                        if (pRow.Fields.get_Field(i).Type == esriFieldType.esriFieldTypeGeometry)
                        {
                            pDataRow["Shape"] = shapeType;
                        }
                        //当图层类型为Anotation时,要素类中会有esriFieldTypeBlob类型的数据,
                        //其存储的是标注内容,如此情况需将对应的字段值设置为Element
                        else if (pRow.Fields.get_Field(i).Type == esriFieldType.esriFieldTypeBlob)
                        {
                            pDataRow[i] = "Element";
                        }
                        else
                        {
                            string o = pRow.get_Value(i).ToString();
                            pDataRow[pRow.Fields.Field[i].Name] = pRow.get_Value(i);
                        }
                    }
                    //设置行选中状态
                    if (selectIDList.Contains(Convert.ToInt32(pDataRow[pTable.OIDFieldName])))
                    {
                        pDataRow["选中要素"] = true;
                    }
                    else
                    {
                        pDataRow["选中要素"] = false;
                    }

                    pDataTable.Rows.Add(pDataRow);
                    pDataRow = null;
                    n++;
                    pRow = pCursor.NextRow();
                }
            }

            //Marshal.ReleaseComObject(pTable);
            return pDataTable;
        }


        /// <summary>
        /// 根据图层字段创建一个只含字段的空DataTable
        /// </summary>
        /// <param name="pLayer"></param>
        /// <param name="tableName"></param>
        /// <returns>返回创建好的空表</returns>
        private DataTable CreateDataTableByLayer(ILayer pLayer, string tableName, bool canSelect = false)
        {
            DataTable pDataTable = new DataTable(tableName);
            ITable pTable = pLayer as ITable;
            IField pField = null;
            DataColumn pDataColumn;

            pDataColumn = new DataColumn("选中要素", typeof(bool));
            pDataColumn.Caption = "选中要素";
            pDataColumn.DefaultValue = false;
            pDataTable.Columns.Add(pDataColumn);

            int oidIndex = pTable.Fields.FindField(pTable.OIDFieldName);
            int shapeIndex = pTable.FindField("Shape");
            IField oidField = pTable.Fields.get_Field(oidIndex);
            IField shapeField = pTable.Fields.get_Field(shapeIndex);
            DataColumn oidDataColumn = new DataColumn(pTable.OIDFieldName);
            oidDataColumn.Unique = true;
            oidDataColumn.AllowDBNull = oidField.IsNullable;
            oidDataColumn.Caption = oidField.AliasName;
            oidDataColumn.DataType = System.Type.GetType(ParseFieldType(oidField.Type));
            oidDataColumn.DefaultValue = oidField.DefaultValue;
            pDataTable.Columns.Add(oidDataColumn);

            pDataColumn = new DataColumn("Shape");
            pDataColumn.AllowDBNull = shapeField.IsNullable;
            pDataColumn.Caption = shapeField.AliasName;
            pDataColumn.DataType = System.Type.GetType(ParseFieldType(shapeField.Type));
            pDataColumn.DefaultValue = shapeField.DefaultValue;
            pDataTable.Columns.Add(pDataColumn);

            for (int i = 0; i < pTable.Fields.FieldCount; i++)
            {
                pField = pTable.Fields.get_Field(i);
                if (pField.Name == pTable.OIDFieldName || pField.Name.ToUpper() == "SHAPE")
                {
                    pField = null;
                    pDataColumn = null;
                    continue;
                }
                pDataColumn = new DataColumn(pField.Name);
                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;
        }


        /// <summary>
        /// 获得图层的Shape类型
        /// </summary>
        /// <param name="pLayer">图层</param>
        /// <returns>返回图形的几何类型</returns>
        private 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 "";
            }
        }

3.3 勾选属性(选择、取消选择)

        //改变所有属性的勾选状态(勾选即选中对应的要素)
        private void gviewAll_CellValueChanging(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
        {
            if (e.Column.FieldName == "选中要素")
            {
                try
                {
                    int rowIndex = e.RowHandle;
                    object o = e.Value;
                    DataRow selectDataRow = allRowsTable.Rows.Find(gviewAll.GetRowCellValue(e.RowHandle, gviewAll.Columns[oidFieldName]));
                    selectDataRow["选中要素"] = o;
                    gridAllAttribute.RefreshDataSource();
                    int oid = Convert.ToInt32(selectDataRow[oidFieldName]);
                    IQueryFilter queryFilter = new QueryFilterClass();
                    queryFilter.WhereClause = featureLayer.FeatureClass.OIDFieldName + "=" + oid;
                    if ((bool)o)
                    {
                        (featureLayer as IFeatureSelection).SelectFeatures(queryFilter, esriSelectionResultEnum.esriSelectionResultAdd, false);
                    }
                    else
                    {
                        (featureLayer as IFeatureSelection).SelectFeatures(queryFilter, esriSelectionResultEnum.esriSelectionResultSubtract, false);
                    }
                    BindingMapControl.Refresh();
                }
                catch (Exception ex)
                {
                    XtraMessageBox.Show("选取要素失败");
                }
            }
        }

3.4 捕获地图选择集改变事件

        //地图刷新
        private void ActiveViewEvents_SelectionChanged()
        {
            UpdateCtrlDataSource();
        }


        /// <summary>
        /// 更新所有属性表(需要在已经初始化DataTable的情况下调用)
        /// </summary>
        private void UpdateCtrlDataSource()
        {
            if (allRowsTable == null || selectionRowsTable == null)
                return;
            try
            {
                if (gridAllAttribute.Visible == true)
                {
                    ICursor pCursor = null;
                    int selectOid;
                    string where = "";
                    selectIDList = new List<int>();
                    DataColumn dataColumn = allRowsTable.Columns["选中要素"];
                    allRowsTable.Columns.Remove(dataColumn);
                    dataColumn.DefaultValue = false;
                    allRowsTable.Columns.Add(dataColumn);

                    IFeatureSelection pFeatureSelection = featureLayer as IFeatureSelection;
                    ISelectionSet pSelectionSet = pFeatureSelection.SelectionSet;
                    pSelectionSet.Search(null, false, out pCursor);
                    IRow pRow = pCursor.NextRow();
                    while (pRow != null)
                    {
                        selectOid = Convert.ToInt32(pRow.get_Value(pRow.Fields.FindField(oidFieldName)));
                        selectIDList.Add(selectOid);
                        pRow = pCursor.NextRow();
                    }
                    if (selectIDList.Count > 0)
                    {
                        foreach (int i in selectIDList)
                        {
                            where += oidFieldName + "=" + i + " or ";
                        }
                        where = where.Substring(0, where.Length - 3);
                        DataRow[] selectRows = allRowsTable.Select(where);
                        foreach (DataRow dataRow in selectRows)
                        {
                            dataRow["选中要素"] = true;
                        }
                    }
                    gridAllAttribute.DataSource = allRowsTable;
                    gviewAll.RefreshData();
                    ctrlGridNavigation1.InitCtrl(allRowsTable, gridAllAttribute, new int[] { 50, 100, 500 });
                }
                if (gridSelectAttribute.Visible == true)
                {
                    RefreshSelectionData();
                    gviewSelect.RefreshData();
                    ctrlGridNavigation1.InitCtrl(selectionRowsTable, gridSelectAttribute, new int[] { 50, 100, 500 });
                }
            }
            catch (Exception ex)
            {
                XtraMessageBox.Show("属性表更新失败");
            }
        }


        /// <summary>
        /// 刷新选择项属性表
        /// </summary>
        public void RefreshSelectionData()
        {
            try
            {
                selectionRowsTable = GetSelectionRowsTable(featureLayer);
                selectionRowsTable.DefaultView.Sort = oidFieldName + " ASC";
                selectionRowsTable = selectionRowsTable.DefaultView.ToTable();
                selectionRowsTable.PrimaryKey = new DataColumn[] { selectionRowsTable.Columns[oidFieldName] };
            }
            catch (Exception ex)
            {
                XtraMessageBox.Show("属性表刷新错误");
            }
        }

3.4 调用控件

注意,在控件初始化时应该传入的地图控件参数应该是IMapControl4,而不是AxMapControl。在上传的代码中有完整的调用示例。

            CtrlAttrubuteGrid ctrlAttrubuteGrid = new CtrlAttrubuteGrid(mapControl, ref featureLayer, queryFilter);
            this.Controls.Add(ctrlAttrubuteGrid);

4、代码下载

优快云下载:优快云下载
github下载:github下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值