今天要介紹的內容比較高級,就是通過可視化的操作進行空間數據的編輯操作。不過這裡面涉及到很多難度比較大的高級功能,例如怎樣選中一個圖元、怎樣移動圖元、怎樣確認圖元的位置以及實現編輯的撤銷操作等等。下面按照自己實現的步驟詳細介紹如下。
1.定義空間數據編輯類的成員變量,具體代碼如下:
[csharp]
private IFeatureWorkspace pFW;
private IMapControl3 m_MapControl; //地圖控件
private IMap m_pMap; //地圖控件中的地圖
private ILayer m_pCurrentLayer; //地圖中的當前操作圖層
private IFeature m_pEditFeature; //當前編輯的要素
private IPoint m_pPoint; //當前鼠標點擊位置
private IDisplayFeedback m_pFeedback; //用於地圖顯示
private IPointCollection m_pPointCollection; //當前要素的點集
private bool m_bInUse; //是否處於同一個編輯狀態
private bool m_bEditingFtr; //是否為編輯要素狀態
private bool m_bSketching; //是否為新建要素狀態
private bool m_bSelecting; //是否為選擇要素狀態
private bool m_bMove; //是否為移動要素狀態
2.初始相關成員變量和數據
[csharp]
private void FrmSpatialDataEdit_Load(object sender, EventArgs e)
{
// Setup the application
m_MapControl = (IMapControl3)axMapControl1.GetOcx(); //獲取地圖控件
m_pMap = m_MapControl.Map;
cboTasks.SelectedIndex = 0;
LoadLayers(); //載入圖層
SetControlStates(); //設置四個命令按鈕狀態
}
上面代碼首先由地圖控件來獲取它的一個實例對象,然後得到地圖控件中的地圖對象,接著就調用函數載入圖層並設置相應操作按鈕的初始化狀態。載入圖層的代碼實現 如下:
[csharp]
/// <summary>
/// 載入圖層,並在地圖空間中加入第一個圖層
/// </summary>
private void LoadLayers()
{
//1.遍歷SDE的每一個獨立要素集中的要素類
IWorkspace pW = MapOperation.GetFeatrueWorkspace() as IWorkspace;
IEnumDataset pED = pW.get_Datasets(esriDatasetType.esriDTFeatureDataset);
IFeatureDataset pFD = pED.Next() as IFeatureDataset;
while (pFD != null)
{
IFeatureClass pFC;
IFeatureClassContainer pFCC = pFD as IFeatureClassContainer;
for (int i = 0; i < pFCC.ClassCount; i++)
{
pFC = pFCC.get_Class(i);
cboLayers.Items.Add(pFC.AliasName);
}
pFD = pED.Next() as IFeatureDataset;
}
//2.遍歷SDE的每一個獨立要素類
pED = pW.get_Datasets(esriDatasetType.esriDTFeatureClass);
IDataset pD = pED.Next();
while (pD != null)
{
IFeatureClass pFC = pD as IFeatureClass;
cboLayers.Items.Add(pFC.AliasName);
pD = pED.Next();
}
cboLayers.SelectedIndex = 0;
AddLayerToMapCtl(cboLayers.SelectedItem.ToString(), true);
}
設置操作按鈕的代碼如下:
[csharp]
/// <summary>
/// 設置四個命令按鍵的功能
/// </summary>
private void SetControlStates()
{
bool bEnabled = InEdit();
btnStartEditing.Enabled = !bEnabled;
btnDelete.Enabled = bEnabled;
btnUndo.Enabled = bEnabled;
btnStopEditing.Enabled = bEnabled;
cboTasks.Enabled = bEnabled;
if (bEnabled)
{
lblTask.ForeColor = Color.Black;
}
else
{
lblTask.ForeColor = Color.Gray;
}
}
也有禁止相應按鈕功能的函數代碼如下:
[csharp]
private void DisableControls()
{
// Disables all but the layer selection combo
btnStartEditing.Enabled = false;
btnDelete.Enabled = false;
btnUndo.Enabled = false;
btnStopEditing.Enabled = false;
lblTask.ForeColor = Color.Gray;
}
3.實現加載圖層到圖層控件中去,這樣就可以在圖形控件中進行編輯操作了,具體加載代碼如下:
[csharp]
/// <summary>
/// 加入圖層到地圖空間中
/// </summary>
/// <param name="layerName">圖層名稱</param>
/// <param name="isVisible">是否顯示</param>
private void AddLayerToMapCtl(string layerName, bool isVisible)
{
if (pFW == null)
{
pFW = MapOperation.GetFeatrueWorkspace();
}
IFeatureClass pFC;
try
{
pFC = pFW.OpenFeatureClass(layerName);
}
catch (Exception)
{
return;
}
IFeatureLayer pFL = new FeatureLayerClass();
pFL.FeatureClass = pFC;
pFL.Name = layerName;
pFL.Visible = isVisible;
axMapControl1.Map.AddLayer(pFL);
axMapControl1.ActiveView.Refresh();
}
4.檢查工作空間中是否有數據處於編輯狀態,是就返回true。
[csharp]
/// <summary>
/// 檢查工作空間中是否有數據處於編輯狀態
/// </summary>
/// <returns>是否正在編輯</returns>
private bool InEdit()
{
// Check edit conditions before allowing edit to stop
if (m_pCurrentLayer == null)
{
return false;
}
IFeatureLayer pFeatureLayer = (IFeatureLayer)m_pCurrentLayer;
if (pFeatureLayer.FeatureClass == null)
{
return false;
}
IDataset pDataset = (IDataset)pFeatureLayer.FeatureClass;
if (pDataset == null)
{
return false;
}
IWorkspaceEdit pWorkspaceEdit = (IWorkspaceEdit)pDataset.Workspace;
if (pWorkspaceEdit.IsBeingEdited())
{
return true;
}
return false;
}
5.開始編輯,使工作空間處於可編輯狀態,在進行圖層編輯前必須調用本方法。
[csharp]
/// <summary>
/// 開始編輯,使工作空間處於可編輯狀態
/// 在進行圖層編輯前必須調用本方法
/// </summary>
private void StartEditing()
{
// Check edit conditions before allowing edit to start
if (m_pCurrentLayer == null)
{
return;
}
if ((IGeoFeatureLayer)m_pCurrentLayer == null)
{
return;
}
IFeatureLayer pFeatureLayer = (IFeatureLayer)m_pCurrentLayer;
IDataset pDataset = (IDataset)pFeatureLayer.FeatureClass;
if (pDataset == null)
{
return;
}
// Start editing, making sure that undo/redo are enabled
// 開始編輯,並設置Undo/Redo 為可用
IWorkspaceEdit pWorkspaceEdit = (IWorkspaceEdit)pDataset.Workspace;
if (!pWorkspaceEdit.IsBeingEdited())
{
pWorkspaceEdit.StartEditing(true);
pWorkspaceEdit.EnableUndoRedo();
LogHelp.writeUpdateDataLog(cboLayers.SelectedItem.ToString(), "1", "update");
}
}
6.刪除當前圖層中選中的地圖對象
[csharp]
/// <summary>
/// 刪除當前圖層中選中的地圖對象
/// </summary>
private void DeleteSelectedFeatures()
{
if (m_pCurrentLayer == null)
{
return;
}
// If there are no features currently selected then nothing to do
IFeatureCursor pFeatureCursor = GetSelectedFeatures();
if (pFeatureCursor == null)
{
return;
}
// Loop over the selected features deleting each in turn
IWorkspaceEdit pWorkspaceEdit = GetWorkspaceEdit();
pWorkspaceEdit.StartEditOperation();
IFeature pFeature = pFeatureCursor.NextFeature();
while (pFeature != null)
{
pFeature.Delete();
pFeature = pFeatureCursor.NextFeature();
}
pWorkspaceEdit.StopEditOperation();
IActiveView pActiveView = (IActiveView)m_pMap;
pActiveView.Refresh();
}
7.撤消以前所做的編輯
[csharp]
/// <summary>
/// 撤消以前所做的編輯
/// </summary>
private void UndoEdit()
{
// Check that editing is possible
if (m_pCurrentLayer == null)
{
return;
}
IFeatureLayer pFeatureLayer = (IFeatureLayer)m_pCurrentLayer;
IDataset pDataset = (IDataset)pFeatureLayer.FeatureClass;
if (pDataset == null)
{
return;
}
/// If edits have taken place then roll-back the last one
IWorkspaceEdit pWorkspaceEdit = (IWorkspaceEdit)pDataset.Workspace;
bool bHasUndos = false;
pWorkspaceEdit.HasUndos(ref bHasUndos);
if (bHasUndos)
{
pWorkspaceEdit.UndoEditOperation();
}
IActiveView pActiveView = (IActiveView)m_pMap;
pActiveView.Refresh();
}
8.停止編輯,並將以前的編輯結果保存到數據文件中。
[csharp]
/// <summary>
/// 停止編輯,並將以前的編輯結果保存到數據文件中。
/// </summary>
private void StopEditing()
{
// Check edit conditions before allowing edit to stop
if (m_pCurrentLayer == null)
{
return;
}
IFeatureLayer pFeatureLayer = (IFeatureLayer)m_pCurrentLayer;
if (pFeatureLayer.FeatureClass == null)
{
return;
}
IDataset pDataset = (IDataset)pFeatureLayer.FeatureClass;
if (pDataset == null)
{
return;
}
// If the current document has been edited then prompt the user to save changes
//如果數據已被修改,則提示用戶是否保存
IWorkspaceEdit pWorkspaceEdit = (IWorkspaceEdit)pDataset.Workspace;
if (pWorkspaceEdit.IsBeingEdited())
{
bool bHasEdits = false;
pWorkspaceEdit.HasEdits(ref bHasEdits);
bool bSave = false;
if (bHasEdits)
{
DialogResult result;
result = MessageBox.Show(this, "是否保存已做的修改?", "提示",
MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (DialogResult.Yes == result)
{
bSave = true;
}
}
pWorkspaceEdit.StopEditing(bSave);
}
m_pMap.ClearSelection();
IActiveView pActiveView = (IActiveView)m_pMap;
pActiveView.Refresh();
}
9.取得選中的地圖對象集合
[csharp]
/// <summary>
/// 取得選中的地圖對象集合
/// </summary>
/// <returns>地圖對象游標</returns>
private IFeatureCursor GetSelectedFeatures()
{
if (m_pCurrentLayer == null)
{
return null;
}
// If there are no features selected let the user know
IFeatureSelection pFeatSel = (IFeatureSelection)m_pCurrentLayer;
ISelectionSet pSelectionSet = pFeatSel.SelectionSet;
if (pSelectionSet.Count == 0)
{
MessageBox.Show("No features are selected in the '" + m_pCurrentLayer.Name + "' layer", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return null;
}
// Otherwise get all of the features back from the selection
ICursor pCursor;
pSelectionSet.Search(null, false, out pCursor);
return (IFeatureCursor)pCursor;
}
10.取得當前圖層所在的工作空間
[csharp]
/// <summary>
/// 取得當前圖層所在的工作空間
/// </summary>
/// <returns>工作空間</returns>
private IWorkspaceEdit GetWorkspaceEdit()
{
if (m_pCurrentLayer == null)
{
return null;
}
IFeatureLayer pFeatureLayer = (IFeatureLayer)m_pCurrentLayer;
IFeatureClass pFeatureClass = pFeatureLayer.FeatureClass;
IDataset pDataset = (IDataset)pFeatureClass;
if (pDataset == null)
{
return null;
}
return (IWorkspaceEdit)pDataset.Workspace;
}
11.向圖層中添加新的地圖對象,並使之處於選中狀態。
[csharp]
/// <summary>
/// 向圖層中添加新的地圖對象,並使之處於選中狀態
/// </summary>
/// <param name="pGeom">圖形對象</param>
private void CreateFeature(IGeometry pGeom)
{
if (pGeom == null)
{
return;
}
if (m_pCurrentLayer == null)
{
return;
}
// Create the feature
IWorkspaceEdit pWorkspaceEdit = GetWorkspaceEdit();
IFeatureLayer pFeatureLayer = (IFeatureLayer)m_pCurrentLayer;
IFeatureClass pFeatureClass = pFeatureLayer.FeatureClass;
pWorkspaceEdit.StartEditOperation();
IFeature pFeature = pFeatureClass.CreateFeature();
pFeature.Shape = pGeom;
pFeature.Store();
pWorkspaceEdit.StopEditOperation();
// Refresh the relevant area of the active view
IActiveView pActiveView = (IActiveView)m_pMap;
if (pGeom.GeometryType == esriGeometryType.esriGeometryPoint)
{
double length;
length = ConvertPixelsToMapUnits(pActiveView, 30);
ITopologicalOperator pTopo = (ITopologicalOperator)pGeom;
IGeometry pBuffer = pTopo.Buffer(length);
pActiveView.PartialRefresh((esriViewDrawPhase)(esriDrawPhase.esriDPGeography | esriDrawPhase.esriDPSelection), m_pCurrentLayer, pBuffer.Envelope);
}
else
{
pActiveView.PartialRefresh((esriViewDrawPhase)(esriDrawPhase.esriDPGeography | esriDrawPhase.esriDPSelection), m_pCurrentLayer, pGeom.Envelope);
}
}
由於這一部分內容太多,剩余的實現功能和內容將在下一篇博客中繼續向下介紹其詳細的代碼實現。
摘自 BruceWoo的專欄