C#Winform+AE開發 空間連線(SpatialJoin)以及欄位對映(FieldMapping)(新手記錄)
阿新 • • 發佈:2018-12-26
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");
}
總結到此為止。還有新增欄位到欄位對映中,不想寫了,等到需要用的時候再寫吧。