DevExpress实现仿ArcMap属性表

在这里插入图片描述
实现的功能:
1.与AxMapControl选择联动 获取AxMapControl选中项记录展示 双击表头缩放
2.属性编辑 可控制允许编辑字段
3.加载效率优化 实现打开时加载固定数量的记录 滑动到底部再次加载固定数量的记录
4.列菜单 字段计算器和计算几何
5.上部菜单 取消选择 反选 按属性选择 删除记录
6.下部菜单 切换显示所有记录和所选记录

构成:属性表使用两个GridControl构成,通过切换可视状态展示记录,上部和下部菜单使用自定义控件,所有控件都放在DockPanel中使其可以拖动。

【显示选择记录】GridView在之后称为选择表
【显示所有记录】GridView在之后称为所有表

1.选择联动的实现
(1)通过AxMapControl选择属性表:
因为的选择表中的记录,在每次只加载固定数量记录得所有表中不一定存在,所有先将AxMapControl中的选择记录更新到选择表中,再在所有表中选中行。绑定AxMapControl左键弹起事件

通过遍历ArcMapControl的要素图层的选择集接口 获取选中的要素 然后加入选择表中

主要方法

获取所有要素图层

        /// <summary>
        /// 获取AxMap内所有要素图层
        /// </summary>
        /// <param name="AXC"></param>
        /// <returns>要素图层列表</returns>
        public static List<IFeatureLayer> GetFeatureLayers(AxMapControl AXC)
        {
            UID uid = new UIDClass();
            uid.Value = "{40A9E885-5533-11d0-98BE-00805F7CED21}";//FeatureLayer
            IEnumLayer a = AXC.Map.Layers[uid];
            List<IFeatureLayer> layers = new List<IFeatureLayer>();
            ILayer IL = null;
            while ((IL = a.Next()) != null)
            {
                layers.Add(IL as IFeatureLayer);
            }
            return layers;
        }

获取选中的要素 然后加入选择表中

        public static void GetSelectionDataTable(IFeatureSelection IFS, string tableName, int startOid = 0, DataTable dt = null, int loadLength = 2000)
        {
        ///参数解释
        IFeatureSelection IFS  :要素图层的选择集  通过 IFeatureLayer as IFeatureLayer获得
        string tableName       :表名称
        int  startOid          :控制开始的Oid  因为每次只加载2000条记录  在下滑到底部后 之前载入的记录不需要再重新载入  通过此参数控制开始载入的OID值
        DataTable dt           :选择表GridControl的数据源DataTable  如果传入此参数  获取到得记录会加入此DataTable中  而不是新生成  DataTable 
        LoadLength             : 需要载入的记录数 (如果为负数 则会载入所有记录)
        ///
            IQueryFilter pQueryFilter;
            DataTable pDataTable;

            if (startOid != 0)
            {
                pDataTable = dt;
                pQueryFilter = new QueryFilterClass();
                pQueryFilter.WhereClause = string.Format("\"{0}\" > {1} ", (IFS as IFeatureLayer).FeatureClass.OIDFieldName, startOid); //筛选OID大于startOid的记录
            }
            else 
            { 
            //startOid为0表示重新生成DataTable 下面的函数是通过图层的字段生成DataTable的列名和格式
                pDataTable = CreateDataTableByLayer(IFS as ILayer, tableName); 
                pQueryFilter = null;
            }

            ISelectionSet ISS = IFS.SelectionSet;
            ICursor cursor;
            ISS.Search(pQueryFilter, false, out cursor);   //获取游标
            // IEnumIDs IID = ISS.IDs;


            //取得图层类型
            string shapeType = getShapeType(IFS as ILayer);   //用来填充Shape字段 
            //创建DataTable的行对象
            DataRow pDataRow = null;
            //从ILayer查询到ITable
            IFeatureLayer IFL = IFS as IFeatureLayer;
            ITable featureTable = IFL.FeatureClass as ITable;


            DataTable AllData = DataProductionPlatform.mainMap.LayerAttributeDict[IFL].GridControlForAll.DataSource as DataTable;
            int id;
            int n = 0;


            IRow irow = cursor.NextRow();
            if (irow == null)
            {  //没有选中记录  赋值选择表的数据源为刚获取的空 DataTable 相当于清空记录
                DataProductionPlatform.mainMap.LayerAttributeDict[IFL].gridControlForSelect.DataSource = pDataTable;
                return;
            }
            while ((id = irow.OID) >= 0)
            {
                DataRow dr = AllData.Rows.Find(id);   //之前将DataTable的索引设置为OID列 因为通过索引搜索更快
                if (dr != null)//如果总表中存在此id 读取总表的行 应该效率更快  
                {
                    pDataTable.ImportRow(dr);
                }
                else //如果总表中不存在此id 读取要素类
                {
                    //新建DataTable的行对象
                    pDataRow = pDataTable.NewRow();
                    for (int i = 0; i < irow.Fields.FieldCount; i++)
                    {
                        switch (irow.Fields.get_Field(i).Type)
                        {
                            case esriFieldType.esriFieldTypeGeometry://如果字段类型为esriFieldTypeGeometry,则根据图层类型设置字段值
                                pDataRow[i] = shapeType;
                                break;
                            //当图层类型为Anotation时,要素类中会有esriFieldTypeBlob类型的数据,
                            //其存储的是标注内容,如此情况需将对应的字段值设置为Element
                            case esriFieldType.esriFieldTypeBlob:
                                pDataRow[i] = "Element";
                                break;
                            default:
                                pDataRow[i] = irow.Value[i];
                                break;
                        }
                    }
                    //添加DataRow到DataTable
                 
                   pDataTable.Rows.Add(pDataRow);
                   
                }
                 n++;
                    //为保证效率,一次只装载最多条记录
                    if (n == loadLength)
                    {
                        break;
                    }
                irow = cursor.NextRow();
                if (irow == null) break;


            }
            System.Runtime.InteropServices.Marshal.ReleaseComObject(cursor);
            if (dt == null) DataProductionPlatform.mainMap.LayerAttributeDict[IFL].gridControlForSelect.DataSource = pDataTable;  //更新选择表的数据源

        }

在选择表更新完成后使用封装好的方法更新所有表的选中行

 /// <summary>
        ///更新GridViewAll的选中项
        /// </summary>
        /// <param name="ifeatureLayer"></param>
        public static void UpdateSelectRow(this IFeatureLayer ifeatureLayer,int StartNum=0)
        {
            ISelectionSet ISS = (ifeatureLayer as IFeatureSelection).SelectionSet;
            IEnumIDs IID = ISS.IDs; 

            DevExpress.XtraGrid.Views.Grid.GridView GVAll = DataProductionPlatform.mainMap.LayerAttributeDict[ifeatureLayer].gridControlForAll.MainView as DevExpress.XtraGrid.Views.Grid.GridView;
            int oid;

            while ((oid = IID.Next()) < StartNum && oid !=-1)  //StartNum之前的行不进行处理
            {
            }
            if(StartNum==0) GVAll.ClearSelection(); //StartNum为0时表示选择集更新  清除All表所有选中项重新选择  StartNum不为0时 表示All表触发了下滑增加记录事件  不清除选择只选择增加的记录
            GVAll.BeginUpdate();//暂停刷新 提升效率

            do
            {
                System.Data.DataTable DT = (GVAll.GridControl.DataSource as System.Data.DataTable);   ///所有表的数据源
                System.Data.DataRow DTrow = DT.Rows.Find(oid);
                if (DTrow != null)
                {
                    int findRow = DT.Rows.IndexOf(DTrow);
                    GVAll.SelectRow(findRow);
                }
                else { break; }  //因为OID按大小排序 如果没找到表示所有表中还未载入到此OID  之后的OID也没有载入  直接跳出循环


            } while ((oid = IID.Next()) >= 0);

            GVAll.EndUpdate();



        }

(2)通过属性表选择AxMapControl:
通过GridView的鼠标弹起事件,首先通过GridView 的Tag属性获取对应的要素图层(打开属性表时就将对应的IFeatureLayer对象放入到GridView的Tag中方便调用),在获取对应的选择集接口,将选中行对应的要素通过ISelectionSet.add添加进选择集

private void UpdateMapSelect(object sender, MouseEventArgs e)
        {
            GridView GV = (GridView)sender;
           if( e.Button==MouseButtons.Left)
            {
                System.Collections.Generic.IList<int> mList = new System.Collections.Generic.List<int>();
                mList = GV.GetSelectedRows();  //获取所有选中行的Handle

                IFeatureSelection ifs = GV.Tag as IFeatureSelection;
                ifs.SelectionSet = null;  //清空要素图层的选择集
                ISelectionSet ISS = ifs.SelectionSet;   ///获取选择集


                foreach (int oid in mList)
                {
                      ISS.Add(int.Parse(GV.GetDataRow(oid)[this.oidString].ToString()));//通过Handle获取对应的行的OID值  this.oidString为之前获取的OID字段名
                }

                ifs.SelectionSet = ISS;  ///将添加后的选择集赋值到要素图层 

                mainMap.LayerAttributeDict[GV.Tag as IFeatureLayer].LoMenu.Updatelabel();
                ///更新下部菜单的选中数量

                axMapC.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, GV.Tag as IFeatureLayer, axMapC.ActiveView.Extent);
                 //刷新显示  仅刷新选择和当前处理的图层  减少卡顿
                (m_pLayer as IFeatureLayer).UpdateSelectGV(false);
                //主要是调用上面的 GetSelectionDataTable方法更新选择集
            }
        }

其他:
1.对 GridView 进行大量更新时,应使用 BeginUpdate() BeginDataUpdate() 停止GridView的刷新 提升数据载入效率。
2.DataTable 应将保存OID的的列设置为主键,需要访问时使用DataTable.Rows.Find(id)方法 ,使用主键获取数据,提升效率。
3.需要对AxMapControl进行刷新操作时应仅刷新修改的部分避免卡顿,axMapC.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, GV.Tag as IFeatureLayer, axMapC.ActiveView.Extent),在保证需求的情况下尽量缩小刷新的部分。
4.仅需要访问OID时使用IEnumIDs接口,获取速度最快

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值