DayDreamInGIS ArcGIS-AddIn 数据处理工具使用说明 之空间连接工具(属性附加)的实现

ArcMap中的空间连接空间,会产生新的要素类,使用该工具,工作中,如果一个生产的数据图层需要去多个图层去获取某些属性,则需要多次空间连接,并产生多个中间结果,且空间连接前后,如果存在字段名称一样的情况,被连接的字段会自动改名,并附加到连接的数据集的后面,工作中,往往需要将通过字段计算器将该字段的内容计算到前一个字段中。

空间连接工具功能界面如下,主要实现将连接图层的字段附加至源图层,而不产生中间成果,同时,支持多要素处理,可以选择只保留一个以及综合,对于源图层已经存在的字段,可以通过选择,实现直接写入已有字段,或者是写入一个新的字段。

下面介绍一下上述功能的实现方式。

一、界面

界面按照上述样式绘制,主要实现对ArcMap中图层数据的获取,以及操作参数的配置。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using GISCommonHelper;

namespace DayDreamInGISTool.SpatialJoin
{
    public partial class frmSJSet : Form
    {
        public frmSJSet()
        {
            InitializeComponent();
            pMap = ArcMap.Document.FocusMap;
        }

        private IMap pMap;
        List<GISCommonHelper.Name_AliasName> fdList;

        private List<string> fields_list = new List<string>();
        /// <summary>
        /// 选定的连接字段
        /// </summary>
        public List<string> Fields_list
        {
            get { return fields_list; }
            set { fields_list = value; }
        }

        /// <summary>
        /// 源图层
        /// </summary>
        private IFeatureLayer pSourceFtlyr;

        public IFeatureLayer PSourceFtlyr
        {
            get { return pSourceFtlyr; }
            set { pSourceFtlyr = value; }
        }

        /// <summary>
        /// 待连接图层
        /// </summary>
        private IFeatureLayer pJoinedFtLyr;

        public IFeatureLayer PJoinedFtLyr
        {
            get { return pJoinedFtLyr; }
            set { pJoinedFtLyr = value; }
        }
        private bool b_summary;
        /// <summary>
        /// 是否综合
        /// </summary>
        public bool B_summary
        {
            get { return b_summary; }
            set { b_summary = value; }
        }

        /// <summary>
        /// 如果连接字段已经存在,值是否写入原字段
        /// </summary>
        private bool b_old;

        public bool B_old
        {
            get { return b_old; }
            set { b_old = value; }
        }

        private void frmSJSet_Load(object sender, EventArgs e)
        {
            pMap = ArcMap.Document.FocusMap;
            CartoLyrHelper.setFeatureLyrCombox(ref cmbSource, pMap, esriGeometryType.esriGeometryAny, false);
            CartoLyrHelper.setFeatureLyrCombox(ref cmbJoinedLyr, pMap, esriGeometryType.esriGeometryAny, false);
        }

        private void cmbJoinedLyr_SelectedIndexChanged(object sender, EventArgs e)
        {
            listView1.Items.Clear();
            if (cmbJoinedLyr.SelectedIndex != -1)
            {
                pJoinedFtLyr = cmbJoinedLyr.SelectedValue as IFeatureLayer;
                listView1.CheckBoxes = true;
                fdList = GISCommonHelper.CartoFieldHelper.getLyrFields(pJoinedFtLyr.FeatureClass.Fields,esriFieldType.esriFieldTypeDate,esriFieldType.esriFieldTypeDouble,esriFieldType.esriFieldTypeInteger,esriFieldType.esriFieldTypeSingle,esriFieldType.esriFieldTypeSmallInteger,esriFieldType.esriFieldTypeString);
                for (int i = 0; i < fdList.Count; i++)
                {
                    ListViewItem lvi = new ListViewItem(fdList[i].alias_name);
                    listView1.Items.Add(lvi);
                }
 
            }
        }

        private void btnAll_Click(object sender, EventArgs e)
        {
            listView1.BeginUpdate();
            //全选
            for (int i = 0; i < listView1.Items.Count; i++)
            {
                ListViewItem lvi = listView1.Items[i];
                lvi.Checked = true;
            }
            listView1.EndUpdate();
        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            listView1.BeginUpdate();
            //全不选
            for (int i = 0; i < listView1.Items.Count; i++)
            {
                ListViewItem lvi = listView1.Items[i];
                lvi.Checked = false;
            }
            listView1.EndUpdate();
        }

        private void btnInverse_Click(object sender, EventArgs e)
        {
            listView1.BeginUpdate();
            //反选
            for (int i = 0; i < listView1.Items.Count; i++)
            {
                ListViewItem lvi = listView1.Items[i];
                lvi.Checked = !lvi.Checked;
            }
            listView1.EndUpdate();
        }

        private void btnOk_Click(object sender, EventArgs e)
        {
            fields_list = new List<string>();

            if (rdbNew.Checked)
                b_old = false;
            else
                b_old = true;

            if (rbdOnly.Checked)
            {
                b_summary = false;
            }
            else
                b_summary = true;

            if (cmbJoinedLyr.SelectedIndex != -1)
            {
                pJoinedFtLyr = cmbJoinedLyr.SelectedValue as IFeatureLayer;
            }
            else { return; }

            if (cmbSource.SelectedIndex != -1)
            {
                pSourceFtlyr = cmbSource.SelectedValue as IFeatureLayer;
            }
            else return;
            for (int i = 0; i < listView1.Items.Count;i++ )
            {
                ListViewItem lvi = listView1.Items[i];
                if (lvi.Checked)
                {
                    fields_list.Add(fdList[i].name);
                }
            }

            this.DialogResult = DialogResult.OK;
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.Cancel;
        }
    }
}

上述代码涉及到Name_AliasName类,name_layer类,此二类主要用于Combox等控件DataSource绑定使用。

/// <summary>
    /// 字段名与假名
    /// </summary>
    public class Name_AliasName
    {
        public string name { get; set; }
        public string alias_name { get; set; }
        public Name_AliasName(string name,string alias_name)
        {
            this.name = name;
            if (string.IsNullOrEmpty(this.alias_name))
            {
                this.alias_name = alias_name;
            }
            else
            {
                this.alias_name = name;
            }
        }
    }

    /// <summary>
    /// 图层名与图层
    /// </summary>
    public class name_Layer{
        public string name { get; set; }
        public ILayer layer { get; set; }
        public Guid id { get; set; }

        public name_Layer(string name,ILayer layer){
            this.name=name;
            this.layer=layer;
            this.id = Guid.NewGuid();
        }
    }

涉及到CartoFieldHelper类,该类主要实现将ArcMap中要素图层绑定至Combox中,以供用户进行点击选择

/// <summary>
    /// 图层辅助类
    /// </summary>
    public class CartoLyrHelper
    {
        #region 设置要素图层Combox
        /// <summary>
        /// 设置要素图层Combox
        /// </summary>
        /// <param name="cmb"></param>
        /// <param name="pMap"></param>
        /// <param name="tp"></param>
        /// <param name="nl">默认选中的图层</param>
        /// <param name="useBlank"></param>
        /// <returns></returns>
        public static List<name_Layer> setFeatureLyrCombox(ref ComboBox cmb, IMap pMap, esriGeometryType tp,name_Layer nl,bool useBlank = false)
        {
            List<name_Layer> lyrlist = setFeatureLyrCombox(ref cmb, pMap, tp, useBlank);
            for (int i = 0; i < cmb.Items.Count; i++)
            {
                name_Layer nltmp = cmb.Items[i] as name_Layer;
                if (nltmp.id == nl.id)
                {
                    cmb.SelectedIndex = i;
                    break;
                }
            }
            return lyrlist;
        }


        /// <summary>
        /// 设置图要素层Combox
        /// </summary>
        /// <param name="cmb"></param>
        /// <param name="pMap"></param>
        /// <param name="tp">几何类型</param>
        /// <param name="useBlank">使用默认的空白项</param>
        /// <returns></returns>
        public static List<name_Layer> setFeatureLyrCombox(ref ComboBox cmb, IMap pMap,esriGeometryType tp,bool useBlank=false)
        {
            cmb.DisplayMember = "name";
            cmb.ValueMember = "layer";
            List<name_Layer> lyrlist = new List<name_Layer>();
            if (useBlank)
            {
                name_Layer nl = new name_Layer("", null);
                lyrlist.Insert(0, nl);
            }
            
            getAllFtlyr(ref lyrlist, pMap,tp);
            cmb.DataSource = lyrlist;
            
            cmb.DropDownStyle = ComboBoxStyle.DropDownList;
            cmb.SelectedIndex = -1;
            return lyrlist;
        }
        #endregion

        #region 设置图层Combox
        public static List<name_Layer> setLyrCombox<T>(ref ComboBox cmb, IMap pMap,name_Layer nl, bool useBlank)
        {
            List<name_Layer> nllist = setLyrCombox<T>(ref cmb, pMap, useBlank);
            for (int i = 0; i < cmb.Items.Count; i++)
            {
                name_Layer nlTmp = cmb.Items[i] as name_Layer;
                if (nlTmp.id == nl.id)
                {
                    cmb.SelectedIndex = i;
                    break;
                }
            }

            return nllist;
        }

        /// <summary>
        /// 设置图层Combox
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="cmb"></param>
        /// <param name="pMap"></param>
        /// <returns></returns>
        public static List<name_Layer> setLyrCombox<T>(ref ComboBox cmb,IMap pMap,bool useBlank=false)
        {
            cmb.DisplayMember = "name";
            cmb.ValueMember = "layer";
            List<name_Layer> lyrlist = new List<name_Layer>();
            if (useBlank)
            {
                name_Layer nl = new name_Layer("", null);
                lyrlist.Insert(0, nl);
            }
            
            getAllLayer<T>(ref lyrlist, pMap);
            
            cmb.DataSource = lyrlist;
            cmb.DropDownStyle = ComboBoxStyle.DropDownList;
            cmb.SelectedIndex = -1;
            return lyrlist;
        }
        #endregion

        #region 获取所有图层
        public static List<T> getAllLayer<T>(IMap pMap)
        {
            List<name_Layer> nllist = new List<name_Layer>();
            getAllLayer<T>(ref nllist, pMap);
            List<T> lyrlist = new List<T>();
            for (int i = 0; i < nllist.Count; i++)
            {
                lyrlist.Add((T)nllist[i].layer);
            }
            return lyrlist;
        }
        #endregion

        #region 获取所有图层集合,适用于Combox
        /// <summary>
        /// 获取图层集合,适用于combox
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="nllist"></param>
        /// <param name="pMap"></param>
        public static void getAllLayer<T>(ref List<name_Layer> nllist, IMap pMap)
        {
            for (int i = 0; i < pMap.LayerCount; i++)
            {
                ILayer plyr = pMap.get_Layer(i);
                if (plyr is T)
                {
                    nllist.Add(new name_Layer(plyr.Name, plyr));
                }
                else if (plyr is IGroupLayer)
                {
                    getGroupLayer<T>(ref nllist, (IGroupLayer)plyr);
                }
            }
        }
        #endregion

        #region 获取所有要素图层
        /// <summary>
        /// 获取所有要素图层
        /// </summary>
        /// <param name="nllist"></param>
        /// <param name="pMap"></param>
        /// <param name="tp"></param>
        public static void getAllFtlyr(ref List<name_Layer> nllist, IMap pMap, ESRI.ArcGIS.Geometry.esriGeometryType tp)
        {
            for (int i = 0; i < pMap.LayerCount; i++)
            {
                ILayer plyr = pMap.get_Layer(i);
                if (plyr is IFeatureLayer)
                {
                    if (((IFeatureLayer)plyr).FeatureClass != null)  //避免图层感叹号时,可能存在的问题
                    {
                        if (tp == esriGeometryType.esriGeometryAny)
                        {
                            nllist.Add(new name_Layer(plyr.Name, plyr));
                        }
                        else
                        {
                            if (((IFeatureLayer)plyr).FeatureClass.ShapeType == tp)
                                nllist.Add(new name_Layer(plyr.Name, plyr));
                        }
                    }
                }
                else if (plyr is IGroupLayer)
                {
                    getGroupLayer(ref nllist, (IGroupLayer)plyr,tp);
                }
            }
        }
        #endregion

        #region 获取图层组的子图层
        /// <summary>
        /// 获取图层组的子图层
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="nllist"></param>
        /// <param name="pGroupLyr"></param>
        private static void getGroupLayer<T>(ref List<name_Layer> nllist, IGroupLayer pGroupLyr)
        {
            ICompositeLayer pCmsLyr = pGroupLyr as ICompositeLayer;
            for (int i = 0; i < pCmsLyr.Count; i++)
            {
                ILayer plyr = pCmsLyr.get_Layer(i);
                if (plyr is T)
                {
                    nllist.Add(new name_Layer(plyr.Name, plyr));
                }
                if (plyr is IGroupLayer)
                {
                    getGroupLayer<T>(ref nllist, (IGroupLayer)plyr);
                }
            }
        }

        /// <summary>
        /// 获取图层组的子图层,只针对于FeatureLayer
        /// </summary>
        /// <param name="nllist"></param>
        /// <param name="pGroupLyr"></param>
        /// <param name="tp"></param>
        private static void getGroupLayer(ref List<name_Layer> nllist, IGroupLayer pGroupLyr,esriGeometryType tp)
        {
            ICompositeLayer pCmsLyr = pGroupLyr as ICompositeLayer;
            for (int i = 0; i < pCmsLyr.Count; i++)
            {
                ILayer plyr = pCmsLyr.get_Layer(i);
                if (plyr is IFeatureLayer)
                {
                    if(((IFeatureLayer)plyr).FeatureClass!=null){
                        if (((IFeatureLayer)plyr).FeatureClass.ShapeType == tp)
                            nllist.Add(new name_Layer(plyr.Name, plyr));
                    }
                }
                if (plyr is IGroupLayer)
                {
                    getGroupLayer(ref nllist, (IGroupLayer)plyr,tp);
                }
            }
        }
        #endregion

        #region 图层更改数据源
        /// <summary>
        /// 根据图层中的数据源的数据集名称设置数据源
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="pLyr"></param>
        /// <param name="pWs"></param>
        public static void setDataSourceByDsname<T>(ILayer pLyr, IWorkspace pWs,string pnm="")
        {
            string dsName;
            if (string.IsNullOrEmpty(pnm))
            {
                dsName = (((IDataLayer)pLyr).DataSourceName as IDatasetName).Name;
            }
            else
            {
                dsName = pnm;
            }

            try
            {
                if (typeof(T) == typeof(IFeatureLayer))
                {
                    IFeatureWorkspace pfws = pWs as IFeatureWorkspace;
                    IFeatureLayer pftLyr = pLyr as IFeatureLayer;
                    pftLyr.FeatureClass = pfws.OpenFeatureClass(dsName);
                }
                else if (typeof(T) == typeof(IRasterLayer))
                {
                    IRasterWorkspace2 prstWorkspace = pWs as IRasterWorkspace2;
                    IRasterLayer prstLyr = pLyr as IRasterLayer;
                    IRasterDataset rasterDataset = prstWorkspace.OpenRasterDataset(dsName);
                    prstLyr.CreateFromDataset(rasterDataset);
                }
            }
            catch (System.Exception ex)
            {
            	//可能会有未知的名称问题导致图层名称更改而无法获取名称的问题
            }
            
        }

        public static void setDataSourceByDsnameTwice<T>(ILayer pLyr, IWorkspace pWs)
        {
            IWorkspace2 pws2 = pWs as IWorkspace2;
            string dsName;
            dsName = (((IDataLayer)pLyr).DataSourceName as IDatasetName).Name;
            esriDatasetType edt;
            if (typeof(T) == typeof(IFeatureLayer))
            {
                edt = esriDatasetType.esriDTFeatureClass;
            }
            else if (typeof(T) == typeof(IRasterLayer))
            {
                edt = esriDatasetType.esriDTRasterDataset;
            }
            else
                edt = esriDatasetType.esriDTAny;

            if(pws2.get_NameExists(edt,dsName))
            {
                setDataSourceByDsname<T>(pLyr, pWs);
            }
            else
            {
                dsName = "_" + dsName;
                if (pws2.get_NameExists(edt, dsName))
                    setDataSourceByDsname<T>(pLyr, pWs,dsName);
                else
                {
                    //不存在,不处理
                }
            }
        }

        /// <summary>
        /// 根据图层的名称设置数据源
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="pLyr"></param>
        /// <param name="pWs"></param>
        public static void setDataSourceByLayerName<T>(ILayer pLyr, IWorkspace pWs)
        {
            string dsName = pLyr.Name;
            if (typeof(T) == typeof(IFeatureLayer))
            {
                IFeatureWorkspace pfws = pWs as IFeatureWorkspace;
                IFeatureLayer pftLyr = pLyr as IFeatureLayer;
                pftLyr.FeatureClass = pfws.OpenFeatureClass(dsName);
            }
            else if (typeof(T) == typeof(IRasterLayer))
            {
                if (dsName.Contains("."))
                    dsName = dsName.Substring(0, dsName.LastIndexOf("."));
                IRasterWorkspace2 prstWorkspace = pWs as IRasterWorkspace2;
                IRasterLayer prstLyr = pLyr as IRasterLayer;
                IRasterDataset rasterDataset = prstWorkspace.OpenRasterDataset(dsName);
                prstLyr.CreateFromDataset(rasterDataset);
            }
        }
        #endregion
    }


二、核心功能

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Framework;
using ESRI.ArcGIS.Display;
using System.Windows.Forms;
using GISCommonHelper;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Editor;

namespace DayDreamInGISTool.SpatialJoin
{
    /// <summary>
    /// 空间连接 属性附加
    /// </summary>
    public class SpatialJoin_AppendBtn : ESRI.ArcGIS.Desktop.AddIns.Button
    {
        public SpatialJoin_AppendBtn()
        {
        }

        private IMap pMap;
        private IFeatureLayer pSourceFtLyr, pJoinedFtlyr;
        /// <summary>
        /// 待附加的字段集合
        /// </summary>
        private List<string> append_fdlist;
        /// <summary>
        /// 多要素是否综合
        /// </summary>
        private bool b_summary;
        /// <summary>
        /// 同名字段时,是否使用已有字段
        /// </summary>
        private bool b_old;
        /// <summary>
        /// 连接要素个数字段名
        /// </summary>
        private string sj_count = "J_Count";
        /// <summary>
        /// 连接要素的Id字段
        /// </summary>
        private string s_Oid = "S_OId";

        private event ProgressDialogHelper.ProgressUpdateHandler ProgressUpdateEvent;        //下一步事件
        private event ProgressDialogHelper.EndHandler EndEvent;  //结束事件
        Guid toolid = Guid.Parse("{D21C8C59-6658-4228-A9D0-12D0A8D22217}");

        protected override void OnClick()
        {
            //if (false)
            //{
            //    ArcMap.Application.CurrentTool = null;
            //    return;
            //}

            //添加字段时,需要关闭编辑模式,否则无法添加字段
            IEditor3 meditor = GISCommonHelper.AddInHelper.geteditor(ArcMap.Application);
            if (meditor.EditState == esriEditState.esriStateEditing)
            {
                MessageBox.Show("请关闭编辑模式");
                return;
            }

            pMap = ArcMap.Document.FocusMap;
            try
            {
                frmSJSet fsjs = new frmSJSet();
                if (fsjs.ShowDialog() == DialogResult.OK)
                {
                    //通过窗体获取空间链接相关参数
                    append_fdlist = fsjs.Fields_list;
                    pSourceFtLyr = fsjs.PSourceFtlyr;
                    pJoinedFtlyr = fsjs.PJoinedFtLyr;
                    b_summary = fsjs.B_summary;
                    b_old = fsjs.B_old;

                    //添加待附加的字段至源图层中.
                    addTFields();

                    //下述代码构建空间缓存,以提高空间检索的效率
                    IWorkspace pSourceWs = (pSourceFtLyr.FeatureClass as IDataset).Workspace;
                    ISpatialCacheManager spatialCacheManager = pSourceWs as ISpatialCacheManager;
                    IEnvelope cacheExtent = (pSourceFtLyr.FeatureClass as IGeoDataset).Extent;
                    if(spatialCacheManager!=null)
                    {
                        //检测是否存在缓存
                        if (!spatialCacheManager.CacheIsFull)
                        {
                           //不过不存在,则创建缓存
                           spatialCacheManager.FillCache(cacheExtent);
                        }
                    }

                    IWorkspace pJoinWS= (pJoinedFtlyr.FeatureClass as IDataset).Workspace;
                    ISpatialCacheManager spatialCacheManager2 = pJoinWS as ISpatialCacheManager;
                    IEnvelope cacheExtent2 = (pJoinedFtlyr.FeatureClass as IGeoDataset).Extent;
                    if (spatialCacheManager2 != null)
                    {
                        //检测是否存在缓存
                        if (!spatialCacheManager2.CacheIsFull)
                        {
                            //不过不存在,则创建缓存
                            spatialCacheManager2.FillCache(cacheExtent2);
                        }
                    }
                    //打开要素工作空间的编辑模式
                    IWorkspaceEdit pwsEdit = pSourceWs as IWorkspaceEdit;
                    pwsEdit.StartEditing(false);
                    pwsEdit.StartEditOperation();
                    int feature_count = pSourceFtLyr.FeatureClass.FeatureCount(null);
                    int count = 0;
                    //配置进度更新对话框
                    ProgressDialogHelper pdh = new ProgressDialogHelper();
                    pdh.Min = 0;
                    pdh.Max = feature_count;
                    pdh.Msg = "正在检索...";
                    pdh.Title = "处理中...";
                    pdh._Application = ArcMap.Application;
                    pdh.InitisalProgressDialog();
                    this.EndEvent += pdh.End;
                    this.ProgressUpdateEvent += pdh.progressNext;

                    //对源图层中所有要素进行遍历
                    IFeatureCursor pSFtcursor = pSourceFtLyr.FeatureClass.Update(null, false);
                    IFeature pSourceFeature = pSFtcursor.NextFeature();
                    while (pSourceFeature != null)
                    {
                        //if (pSourceFeature.OID != 48)
                        //{
                        //    pSourceFeature = pSFtcursor.NextFeature();
                        //    continue;
                        //}
                        search(ref pSourceFeature);
                        pSFtcursor.UpdateFeature(pSourceFeature);
                        pSourceFeature = pSFtcursor.NextFeature();
                        count++;
                        if (ProgressUpdateEvent != null)
                        {
                            ProgressUpdateEvent(count);
                        }
                        //System.Diagnostics.Debug.WriteLine(count);
                    }
                    if (EndEvent != null)
                        EndEvent();
                    //pSFtcursor.Flush();

                    //保存编辑
                    pwsEdit.StopEditOperation();
                    pwsEdit.StopEditing(true);
                    MessageBox.Show("处理完成");

                    //清除缓存
                    if(spatialCacheManager!=null)
                        spatialCacheManager.EmptyCache();
                    if(spatialCacheManager2!=null)
                        spatialCacheManager2.EmptyCache();
                }
            }
            catch (System.Exception ex)
            {

                MessageBox.Show("发生未知异常,ErrorCode:{B74639EE-B057-4CCF-B9DA-3D0155F7EC28},消息:" + ex.Message);
            }
            //finally
            //{
                
            //}
        }

        /// <summary>
        /// 检索并设置要素的附加字段的值.
        /// </summary>
        /// <param name="pSourceFeature"></param>
        private void search(ref IFeature pSourceFeature)
        {
            //以源图层中的要素进行空间检索
            ISpatialFilter psf = new SpatialFilterClass();
            IGeometry pGeo = pSourceFeature.Shape;
            ITopologicalOperator ptop = pGeo as ITopologicalOperator;
            ptop.Simplify();  //简化
            psf.Geometry = ptop as IGeometry;
            psf.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;
            IFeatureCursor pftcursor = pJoinedFtlyr.FeatureClass.Search(psf, false);
            IFeature pJFeature = pftcursor.NextFeature();
            //检索到的要素集合
            List<IFeature> search_list = new List<IFeature>();
            while (pJFeature != null)
            {
                search_list.Add(pJFeature);
                if (b_summary)
                {
                }
                else
                {
                    break;
                }

                pJFeature = pftcursor.NextFeature();
            }

            //字段内容处理
            int source_fdIndex, join_fdIndex;
            IField psourefd;
            object val=0;
            for (int i = 0; i < append_fdlist.Count; i++)
            {
                source_fdIndex = pSourceFeature.Fields.FindField(append_fdlist[i]);
                //此处存在Bug,如果存在源图层字段与连接图层字段重复,并选择了保留两个字段时,会存在Bug
                join_fdIndex = pJoinedFtlyr.FeatureClass.Fields.FindField(append_fdlist[i]);
                psourefd = pSourceFeature.Fields.get_Field(source_fdIndex);
                switch (psourefd.Type)
                {
                    case esriFieldType.esriFieldTypeString:
                    case esriFieldType.esriFieldTypeDate:
                        //连接
                        string str = "";
                        if (search_list.Count == 0)
                        {

                        }
                        else
                        {
                            //字符类型进行连接
                            val = "";
                            for (int j = 0; j < search_list.Count; j++)
                            {
                                string Vl = search_list[j].get_Value(join_fdIndex).ToString();
                                if (!string.IsNullOrWhiteSpace(Vl))
                                {
                                    str += Vl + ",";
                                }
                            }
                            if (str.Length != 0)
                            {
                                if (str[str.Length - 1] == ',')
                                {
                                    val = str.Remove(str.Length - 1);
                                }
                            }

                            if (pSourceFeature.Fields.get_Field(source_fdIndex).Name == "FNUMBER")
                            {
                                System.Diagnostics.Debug.WriteLine("开始调试");
                            }
                            //此时需要判断是否可能超限
                            if (psourefd.Length < str.Length)
                            {
                                val = str.Substring(0, psourefd.Length - 1);  //防止超过长度
                            }
                        }
                        
                        break;
                    case esriFieldType.esriFieldTypeSmallInteger:
                        val = summary<int>(search_list, join_fdIndex);
                        break;
                    case esriFieldType.esriFieldTypeSingle:
                        val = summary<Single>(search_list, join_fdIndex);
                        break;
                    case esriFieldType.esriFieldTypeInteger:
                        val = summary<long>(search_list, join_fdIndex);
                        break;
                    case esriFieldType.esriFieldTypeDouble:
                        val = summary<double>(search_list, join_fdIndex);
                        break;
                }
                
                pSourceFeature.set_Value(source_fdIndex, val);
            }

            //设置写入个数,源OId
            if (search_list.Count == 0)
            {

            }
            else
            {
                string strt = "";
                for (int i = 0; i < search_list.Count; i++)
                {
                    strt += search_list[i].OID.ToString() + ",";
                }
                strt = strt.Remove(strt.Length - 1);
                //判断长度是否超限
                int s_oid_length = pSourceFeature.Fields.get_Field(pSourceFeature.Fields.FindField(s_Oid)).Length;
                if (s_oid_length < strt.Length)
                {
                    strt = strt.Substring(0, s_oid_length - 5) + ">>";
                }
                pSourceFeature.set_Value(pSourceFeature.Fields.FindField(s_Oid), strt);
            }
            pSourceFeature.set_Value(pSourceFeature.Fields.FindField(sj_count), search_list.Count);

            System.Runtime.InteropServices.Marshal.ReleaseComObject(pftcursor);
            System.Runtime.InteropServices.Marshal.ReleaseComObject(psf);

            System.GC.Collect();
            System.GC.WaitForPendingFinalizers();//挂起当前线程,直到处理终结器队列的线程清空该队列为止。
        }

        private object summary<T>(List<IFeature> ftlist,int fdIndex)
        {
            if (typeof(T) == typeof(System.Double))
            {
                double tmp = 0;
                for (int j = 0; j < ftlist.Count; j++)
                {
                    double t = 0;
                    string st = ftlist[j].get_Value(fdIndex).ToString();
                    if (double.TryParse(st, out t))
                    {
                        tmp += t;
                    }
                }
                return tmp;
            }
            if (typeof(T) == typeof(System.Int32))
            {
                int tmp = 0;
                for (int j = 0; j < ftlist.Count; j++)
                {
                    int t = 0;
                    string st = ftlist[j].get_Value(fdIndex).ToString();
                    if (int.TryParse(st, out t))
                    {
                        tmp += t;
                    }
                }
                return tmp;
            }
            if (typeof(T) == typeof(System.Single))
            {
                Single tmp = 0;
                for (int j = 0; j < ftlist.Count; j++)
                {
                    string stt = ftlist[j].get_Value(fdIndex).ToString();
                    Single t = 0;
                    if (Single.TryParse(stt, out t))
                    {
                        tmp += t;
                    }
                }
                return tmp;
            }
            if (typeof(T) == typeof(System.Int64))
            {
                long tmp = 0;
                for (int j = 0; j < ftlist.Count; j++)
                {
                    long t = 0;
                    string st=ftlist[j].get_Value(fdIndex).ToString();
                    if(long.TryParse(st,out t)){
                        tmp+=t;
                    }
                }
                return tmp;
            }
            else
                return null;
        }

        /// <summary>
        /// 添加附加字段
        /// </summary>
        private void addTFields()
        {
            //添加附加字段 添加字段通过IClass接口实现
            IClass pClass = pSourceFtLyr.FeatureClass as IClass;

            for (int i = 0; i < append_fdlist.Count; i++)
            {
                string fdnm = append_fdlist[i];
                if (addHasFd(pClass, ref fdnm))
                {
                    append_fdlist[i] = fdnm;  //字段名称发生变化时,更新待附加字段集合中的名称
                }
            }

            //添加Join_Count,源Oid字段
            if (pClass.Fields.FindField(sj_count) == -1)
            {
                IField pfd = new FieldClass();
                IFieldEdit pfdEdit = pfd as IFieldEdit;
                pfdEdit.Name_2 = sj_count;
                pfdEdit.Type_2 = esriFieldType.esriFieldTypeSmallInteger;
                pClass.AddField(pfd);
            }

            if (pClass.Fields.FindField(s_Oid) == -1)
            {
                IField pfd = new FieldClass();
                IFieldEdit pfdEdit = pfd as IFieldEdit;
                pfdEdit.Name_2 = s_Oid;
                pfdEdit.Type_2 = esriFieldType.esriFieldTypeString;
                pfdEdit.Length_2 = 200;
                pClass.AddField(pfd);
            }
        }


        /// <summary>
        /// 添加字段名称,如果字段名称没有变化,返回false,字段名称变化了,返回true
        /// </summary>
        /// <param name="pClass"></param>
        /// <param name="fdnm"></param>
        /// <returns></returns>
        private bool addHasFd(IClass pClass,ref string fdnm)
        {
            IField pSFd = pJoinedFtlyr.FeatureClass.Fields.get_Field(pJoinedFtlyr.FeatureClass.FindField(fdnm));

            if (pClass.FindField(fdnm) == -1)
            {
                //在源图层中检索待附加字段,不存在该字段,则添加.
                IClone pClone = pSFd as IClone;  //通过AE提供的IClone接口,直接从待连接图层的字段中复制一个对象
                IFieldEdit pNFD = pClone.Clone() as IFieldEdit;
                pNFD.IsNullable_2 = true;
                pClass.AddField(pNFD);
                return false;
            }
            else
            {
                //如果源图层存在该字段
                if (!b_old)
                {
                    //配置不使用原字段,则创建新字段
                    fdnm = fdnm.Remove(fdnm.Length - 1, 1);
                    fdnm = fdnm + "T";  //移除字段名的最后一个字符,并替换为"T",特殊情况下,可能存在还是与原字段名一致的问题
                    IFieldEdit psfdEdit = pSFd as IFieldEdit;
                    psfdEdit.Name_2 = fdnm;
                    pClass.AddField(psfdEdit as IField);
                    return true;
                }
                else
                {
                    //配置使用原字段
                    return false;
                }
            }
        }

        protected override void OnUpdate()
        {
        }
    }
}
发布了22 篇原创文章 · 获赞 12 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/u012839776/article/details/97180638
今日推荐