1. 程式人生 > >C#Winform+AE開發 空間連線(SpatialJoin)以及欄位對映(FieldMapping)(新手記錄)

C#Winform+AE開發 空間連線(SpatialJoin)以及欄位對映(FieldMapping)(新手記錄)

1,佈局

連線要素的欄位對映控制元件使用的是列表框ListBox

2,獲取目標要素和連線要素

使用兩種方式,一是自動獲取當前地圖載入的圖層

            #region 獲取主視窗圖層並新增到控制元件中
            IMap myMap = form.getMapControl().Map;
            IFeatureLayer pFeatLayer;
            IFeatureClass pFeatureClass;
            ICompositeLayer pCompLayer;
            //遍歷地圖
            for (int i = 0; i < myMap.LayerCount; i++)
            {
                if (myMap.get_Layer(i) is IFeatureLayer)
                {
                    //獲得圖層要素
                    pFeatLayer = myMap.get_Layer(i) as IFeatureLayer;
                    pFeatureClass = pFeatLayer.FeatureClass;
                    if (pFeatureClass.ShapeType == esriGeometryType.esriGeometryPoint || pFeatureClass.ShapeType == esriGeometryType.esriGeometryLine || pFeatureClass.ShapeType == esriGeometryType.esriGeometryPolyline)
                    {
                        ComboxTarget.Items.Add(pFeatLayer.Name);
                    }
                    if (pFeatureClass.ShapeType == esriGeometryType.esriGeometryPolygon)
                    {
                        ComboxJoin.Items.Add(pFeatLayer.Name);
                    }
                }
                else if (myMap.get_Layer(i) is IGroupLayer)
                {
                    string name = myMap.get_Layer(i).Name;
                    //遍歷圖層組
                    pCompLayer = myMap.get_Layer(i) as ICompositeLayer;
                    for (int j = 0; j < pCompLayer.Count; j++)
                    {
                        if (pCompLayer.get_Layer(j) is IFeatureLayer)
                        {
                            pFeatLayer = pCompLayer.get_Layer(j) as IFeatureLayer;
                            pFeatureClass = pFeatLayer.FeatureClass;
                            if (pFeatureClass.ShapeType == esriGeometryType.esriGeometryPoint || pFeatureClass.ShapeType == esriGeometryType.esriGeometryLine || pFeatureClass.ShapeType == esriGeometryType.esriGeometryPolyline)
                            {
                                ComboxTarget.Items.Add(name + @"\" + pFeatLayer.Name);
                            }
                            if (pFeatureClass.ShapeType == esriGeometryType.esriGeometryPolygon)
                            {
                                ComboxJoin.Items.Add(name + @"\" + pFeatLayer.Name);
                            }
                        }
                    }
                }
            }
            #endregion

二是,從檔案中選擇圖層並新增

#region 從檔案中選擇輸入圖層新增到控制元件中
            openFileDialog1.FileName = "";
            openFileDialog1.Filter = "要素類|*.shp;*.dwg";
            openFileDialog1.FilterIndex = 1;
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                if (System.IO.Path.GetExtension(openFileDialog1.FileName) == ".DWG" || System.IO.Path.GetExtension(openFileDialog1.FileName) == ".dwg")
                {
                    FileInfo fileInfo = new FileInfo(openFileDialog1.FileName);
                    string path = fileInfo.Directory.ToString();
                    string fileName = fileInfo.Name;

                    IWorkspaceFactory pCadWorkspaceFactory = new CadWorkspaceFactoryClass();
                    IFeatureWorkspace pFeatureWorkspace = (IFeatureWorkspace)pCadWorkspaceFactory.OpenFromFile(path, 0);

                    IFeatureDataset pFeatureDataset = pFeatureWorkspace.OpenFeatureDataset(fileName);
                    IFeatureClassContainer pFeatureClassContainer = pFeatureDataset as IFeatureClassContainer;
                    //遍歷CAD檔案中的每個要素
                    for (int i = 0; i < pFeatureClassContainer.ClassCount; i++)
                    {
                        IFeatureClass pFeatureClass = pFeatureClassContainer.get_Class(i);
                        if (pFeatureClass.FeatureType != esriFeatureType.esriFTCoverageAnnotation)
                        {
                            IFeatureLayer pFeatureLayer = new FeatureLayerClass();
                            pFeatureLayer.Name = pFeatureClass.AliasName;
                            pFeatureLayer.FeatureClass = pFeatureClass;
                            if (pFeatureClass.ShapeType == esriGeometryType.esriGeometryPoint || pFeatureClass.ShapeType == esriGeometryType.esriGeometryLine || pFeatureClass.ShapeType == esriGeometryType.esriGeometryPolyline)
                            {
                                this.ComboxTarget.Items.Add(openFileDialog1.FileName + @"\" + pFeatureLayer.Name);
                            }
                        }

                    }
                }
                else
                {
                    this.ComboxTarget.Items.Add(openFileDialog1.FileName);
                }
            }
            #endregion

3,關於欄位對映

返回輸入圖層的完整路徑

        #region 返回輸入圖層路徑
        public string getInputLayerValue(string textValue)
        {
            #region 引數定義
            string InputValue = null;
            string mValue = textValue;
            IMap myMap = form.getMapControl().Map;
            IFeatureLayer[] pFeatureLayers = MyFeatureLayer.GetMyFeatureLayers(myMap);
            #endregion

            #region 獲取輸入點圖層
            if (mValue.Contains(":"))//來自檔案選擇
            {
                InputValue = mValue;
            }
            else //來自主視窗載入圖層
            {
                if (mValue.Contains(@"\")) //CAD要素類
                {
                    int m = mValue.LastIndexOf(@"\");
                    string pValue = mValue.Substring(m + 1);
                    for (int i = 0; i < pFeatureLayers.Length; i++)//選擇地圖控制元件中與下拉框同名的地圖圖層
                    {
                        if (pFeatureLayers[i].Name == pValue)
                        {
                            ILayer mLayer = pFeatureLayers[i];
                            IDataLayer dataLayer = mLayer as IDataLayer;
                            IDatasetName pDsName = (IDatasetName)(dataLayer.DataSourceName);
                            IWorkspaceName wsName = pDsName.WorkspaceName;
                            string pathStr = wsName.PathName;
                            string fileName = mValue;
                            string fullName = System.IO.Path.Combine(pathStr, fileName);
                            InputValue = fullName;
                            break;
                        }
                    }
                }
                else //shp圖層
                {
                    for (int i = 0; i < pFeatureLayers.Length; i++)//選擇地圖控制元件中與下拉框同名的地圖圖層
                    {
                        if (pFeatureLayers[i].Name == mValue)
                        {
                            ILayer mLayer = pFeatureLayers[i];
                            IDataLayer dataLayer = mLayer as IDataLayer;
                            IDatasetName pDsName = (IDatasetName)(dataLayer.DataSourceName);
                            IWorkspaceName wsName = pDsName.WorkspaceName;
                            string pathStr = wsName.PathName;
                            string fileName = pDsName.Name + ".shp";
                            string fullName = System.IO.Path.Combine(pathStr, fileName);
                            InputValue = fullName;
                            break;
                        }
                    }
                }
            }
            return InputValue;
            #endregion
        }
        #endregion

新增欄位對映,顯示的模式是:圖層名.欄位名(欄位型別)

        IGPUtilities gputilities = new GPUtilitiesClass();//gp應用程式類
        IGPFieldMapping mFieldMapping = new GPFieldMappingClass();
        IArray Tables = new ArrayClass();
        string pathA = "";
        string pathB = "";
        string TargetValue = null;
        string JoinValue = null;
        List<string> TargetFNlist = new List<string>();
        private void ComboxTarget_TextChanged(object sender, EventArgs e)
        {
            TargetFNlist.Clear();
            IDETable TargetTable;
            if (ComboxTarget.Text.Length > 0)
            {
                TargetValue = getInputLayerValue(ComboxTarget.Text);
                string tName = System.IO.Path.GetFileName(ComboxTarget.Text);
                //新增欄位對映
                pathA = TargetValue;
                TargetTable = (IDETable)gputilities.MakeDataElement(pathA, null, null);
                Tables.Add(TargetTable);
                mFieldMapping.Initialize(Tables, null);
                for (int i = 0; i < mFieldMapping.Fields.FieldCount; i++)
                {
                    IField pField = mFieldMapping.Fields.get_Field(i);
                    IFieldEdit pEditField = (IFieldEdit)pField;
                    TargetFNlist.Add(tName + "." + pField.Name + "(" + MyFieldType.SetMyFieldType(pEditField.Type) + ")");
                }
            }
            else
            {
                MessageBox.Show("還沒有選擇目標要素,請選擇!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
        }

 關於MyFieldType.SetMyFieldType(pEditField.Type),自定義的一個類,用來將英文的欄位型別轉為中文顯示

 public static string SetMyFieldType(esriFieldType fieldType)//將EsriType 轉換為String
        {
            switch (fieldType)
            {
                case esriFieldType.esriFieldTypeSmallInteger:
                    return "短整型";
                case esriFieldType.esriFieldTypeInteger:
                    return "長整型";
                case esriFieldType.esriFieldTypeSingle:
                    return "浮點型";
                case esriFieldType.esriFieldTypeDouble:
                    return "雙精度";
                case esriFieldType.esriFieldTypeString:
                    return "文字";
                case esriFieldType.esriFieldTypeDate:
                    return "日期";
                case esriFieldType.esriFieldTypeOID:
                    return "物件ID";
                case esriFieldType.esriFieldTypeGeometry:
                    return "幾何";
                default:
                    return "文字";
            }
        }

重新命名對映欄位

        //定義一個文字框
        TextBox txtEdit = new TextBox(); 
        public SpatialJoinForm()
        {
            InitializeComponent();
            txtEdit.KeyDown += new KeyEventHandler(txtEdit_KeyDown); 
        }

        /// <summary>  
        /// 點選其它項 隱藏編輯框  
        /// </summary>  
        private void ListboxFields_MouseClick(object sender, MouseEventArgs e)
        {
            txtEdit.Visible = false;
        }

        /// <summary>  
        /// 雙擊項時顯示編輯框  
        /// </summary>  
        private void ListboxFields_DoubleClick(object sender, EventArgs e)
        {
            if (ListboxFields.Items.Count > 0)
            {
                int itemSelected = ListboxFields.SelectedIndex;
                string itemText = ListboxFields.Items[itemSelected].ToString();
                string TXT = mFieldMapping.Fields.get_Field(ListboxFields.SelectedIndex).Name;

                Rectangle rect = ListboxFields.GetItemRectangle(itemSelected);
                txtEdit.Parent = ListboxFields;
                txtEdit.Bounds = rect;
                txtEdit.Multiline = true;
                txtEdit.Visible = true;
                txtEdit.Text = TXT;
                txtEdit.Focus();
                txtEdit.SelectAll();
            }
        }
        /// <summary>  
        /// KeyDown事件定義  重新命名欄位
        /// </summary>  
        private void txtEdit_KeyDown(object sender, KeyEventArgs e)
        {
            //Enter鍵 更新項並隱藏編輯框  
            if (e.KeyCode == Keys.Enter)
            {
                IField ifd = mFieldMapping.Fields.get_Field(ListboxFields.SelectedIndex);
                IFieldEdit ife = (IFieldEdit)ifd;
                ife.Name_2 = txtEdit.Text;
                IGPFieldMap mFieldMap = mFieldMapping.GetFieldMap(ListboxFields.SelectedIndex);
                mFieldMap.OutputField = ife;
                mFieldMapping.ReplaceFieldMap(ListboxFields.SelectedIndex, mFieldMap);//修改欄位名

                string path = mFieldMapping.GetFieldMap(ListboxFields.SelectedIndex).Fields.get_Field(0).Name.ToString();
                string name = System.IO.Path.GetFileName(path);
                int r = name.LastIndexOf(".shp");
                string filename = name.Substring(0, r);
                string type = MyFieldType.SetMyFieldType(mFieldMapping.Fields.get_Field(ListboxFields.SelectedIndex).Type);
                ListboxFields.Items[ListboxFields.SelectedIndex] = filename + "." + txtEdit.Text + "(" + type + ")";
                txtEdit.Visible = false;
            }
            //Esc鍵 直接隱藏編輯框  
            if (e.KeyCode == Keys.Escape)
                txtEdit.Visible = false;
        }

刪除欄位

        //刪除欄位
        private void BtnDelete_Click(object sender, EventArgs e)
        {
            if (ListboxFields.SelectedIndex > -1)
            {
                mFieldMapping.RemoveFieldMap(ListboxFields.SelectedIndex);
                ListboxFields.Items.RemoveAt(ListboxFields.SelectedIndex);
            }
        }

欄位對映中所選欄位的合併規則,使用了列表框的右鍵選單contextMenuStrip1

        //右鍵點選ListBox的Item選中並彈出選單
        private void ListboxFields_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                System.Drawing.Point p = e.Location;//獲取點選的位置
                int currentIndex = ListboxFields.IndexFromPoint(p);//根據位置獲取右鍵點選項的索引
                if (ListboxFields.Items.Count > 0)
                {
                    this.ListboxFields.SetSelected(currentIndex, true);
                    if (currentIndex == ListboxFields.SelectedIndex)
                    {
                        this.ListboxFields.ContextMenuStrip = contextMenuStrip1;
                    }
                    else
                    {
                        this.ListboxFields.ContextMenuStrip = null;
                    }
                }
                else
                {
                    this.ListboxFields.ContextMenuStrip = null;
                }
            }
        }

關於選中一個item時,前面顯示對號,使用了最死板的方法,程式碼重複性很高,有待改進。關於圖片,使用的是資原始檔,解決方案右擊,選擇屬性,開啟後按圖選擇,新增現有檔案,新增下載的PNG之類的圖片(16 * 16)即可

   

        #region 欄位對映中所選欄位的合併規則
        IGPFieldMap mrFieldmap;
        private void firstToolStripMenuItem_Click(object sender, EventArgs e)
        {
            firstToolStripMenuItem.Image = Properties.Resources.對號;
            lastToolStripMenuItem.Image = null;
            joinToolStripMenuItem.Image = null;
            sumToolStripMenuItem.Image = null;
            meanToolStripMenuItem.Image = null;
            medianToolStripMenuItem.Image = null;
            modeToolStripMenuItem.Image = null;
            minToolStripMenuItem.Image = null;
            maxToolStripMenuItem.Image = null;
            standardDeviationToolStripMenuItem.Image = null;
            countToolStripMenuItem.Image = null;
            //MessageBox.Show(ListboxFields.SelectedIndex.ToString());//所選行的Index
            //MessageBox.Show(ListboxFields.SelectedItem.ToString());//所選行的值
            mrFieldmap= mFieldMapping.GetFieldMap(ListboxFields.SelectedIndex);
            mrFieldmap.MergeRule =esriGPFieldMapMergeRule.esriGPFieldMapMergeRuleFirst;
            mFieldMapping.ReplaceFieldMap(ListboxFields.SelectedIndex, mrFieldmap);
        }
        依次響應點選事件,修改Image和MergeRule,程式碼省略……
        ……………………………………………………………………………………………………………………………………………………       
        #endregion

重置欄位對映,即重新獲取圖層的全部欄位,發生在不小心刪除了不該刪除的欄位之後

        //重置欄位
        private void BtnReset_Click(object sender, EventArgs e)
        {
            ListboxFields.Items.Clear();
            mFieldMapping.RemoveAll();
            mFieldMapping.Initialize(Tables, null);
            for (int i = 0; i < TargetFNlist.Count; i++)
            {
                ListboxFields.Items.Add(TargetFNlist[i]);
            }
        }

執行空間連線,並返回執行進度或錯誤提示

            Geoprocessor gp = new Geoprocessor();
            ESRI.ArcGIS.AnalysisTools.SpatialJoin sj = new ESRI.ArcGIS.AnalysisTools.SpatialJoin();
            IGeoProcessorResult2 JSresult = null;

            //關於獲取輸入圖層和判斷輸出圖層名稱是否有誤程式碼省略……
            ……………………………………………………

            sj.target_features = TargetValue;
            sj.join_features = JoinValue;
            sj.out_feature_class = TextBoxOutput.Text;
            sj.join_operation = JoinOperation.Text;
            sj.join_type = "KEEP_ALL";
            sj.match_option = ComboxMatchOption.Text;
            sj.field_mapping = mFieldMapping;
            //執行並返回錯誤資訊
            try
            {
                JSresult = gp.Execute(sj, null) as IGeoProcessorResult2;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "GP Error");
            }
            finally
            {
                System.Text.StringBuilder sb = new System.Text.StringBuilder();
                for (int i = 0; i < gp.MessageCount; i++)
                    sb.AppendLine(gp.GetMessage(i));
                if (sb.Capacity > 0) MessageBox.Show(sb.ToString(), "GP Messages");
            }

總結到此為止。還有新增欄位到欄位對映中,不想寫了,等到需要用的時候再寫吧。