How to listen to edit events


SummaryThis article describes how to use edit event notifications to execute edit operations.

Development licensing Deployment licensing
ArcEditor ArcView
ArcInfo ArcEditor
ArcView ArcInfo

Additional Requirements
  • In addition to the system namespace, this code requires shorthand access to the Editor, Geodatabase, Geometry, Application Developer Framework (ADF), Display, Carto, and ArcMapUI namespaces.

In this topic


Listening to edit events

Commands and other objects are implemented to listen for edit events that are fired and respond to the events by executing the custom event handler code. Tools that listen to the editor and respond to users' actions are the actions that fire the events. Events are put in place to trap what the user is doing. Understanding the order in which events fire can help you to define which object should capture the event as an event receiver. Refer to IEditEvents for supported events and when you may want to use them.
 
Some common editing scenarios that fire events on this interface consider the editing operation that may fire the event. Many events fire in response to different actions.
 

Common workflow

The following shows common workflow steps and the events that trap in the order they fire:
 
Start an edit session:
 
Set the target layer:
 
Edit an existing feature and start by changing the task to modify the feature:
 
Enter a value in the attribute inspector:
 
Update attributes of a feature that has a related table that also updates:
 
Select a feature:
 
Delete a feature:
 
Create new features using the Sketch tool to draw a feature:
 
Continue to add vertices:
 
Save edit commands from the editor menu:
 
Enable edit sketch of existing feature and modify the feature geometry:
 
Change the current z—Note clicking the map canvas to fire the event:
 
Move an existing annotation feature:
 
Insert a vertex into a sketch:
(The OnVertexAdded event does not fire. To understand how to force this event to fire, see Special IEditEvents2 methods.)
 
Deleted a vertex:
(This event also does not fire when using the edit tool; see Special IEditEvents2 methods.)
 
Stop editing:
 
Undo operation:

Redo operation:
As you can see from the previous common workflow, some events are fired more frequently than others, even when you want to catch the event. These events, such as OnSelectionChanged, BeforeDrawSketch, and AfterDrawSketch, can be delayed until you want to trap the event by implementing the IEditor.DelayEvents method.

More workflow scenarios using edit events

When working with events that happen during feature editing consider the following:
 
When doing versioned edits and version conflicts arise, consider the following:

Edit session environment

When starting and stopping an edit session, a safe practice is to add a listener to determine when the edit session starts and stops. The start and stop editing commands will fire these events; however, they can also be fired when IEditor.StopEditing is called.
 
An unsafepractice is to programmatically stop or disrupt the edit session inside the method that is handling the event. The IEditor.StopEditing method should not appear inside the event handler due to the other events that are still firing. This results in these events being disrupted and may cause unexpected behavior.

Trapping events when StartEditing is called from the workspace instead of the editor

The OnStartEditing event is fired from the editor when Start Editing is clicked on the Editor toolbar; many times it is called programmatically. The IWorkspaceEdit.StartEditing method is broadcast to IWorkspaceEditEvents, and from this interface, the OnStartEditing event is fired after editing is started on a workspace. A parameter is the undo/redo Boolean. When undo/redo is true, you must also use the StartEditOperation method. By using this method, the geodatabase broadcasts events from the IWorkspaceEditEvents and IVersionEvents interfaces.
 

Considerations when using insert cursors and trapping events

Using existing editor tools is a common practice that raises a consideration when the developer is also listening to editor events. See the following: 
 
When the following lines of code are added to the start editing event, this forces store for all the simple classes in the workspace on StartEditing:
 

[C#]
IWorkspaceEditControl pWorkspaceEditControl = m_editor.EditWorkspace as IWorkspaceEditControl;
pWorkspaceEditControl.SetStoreEventsRequired();

[VB.NET]
Dim pWorkspaceEditControl As IWorkspaceEditControl
Set pWorkspaceEditControl = CType(m_editor.EditWorkspace, IWorkspaceEditControl)
pWorkspaceEditControl.SetStoreEventsRequired()

Edit events in the object model diagram

The following illustrates edit events in the object model diagram:
 
 

Using the IEditEvents2 and IEditEvents3 interfaces

The following describes using the IEditEvents2 and IEditEvents3 interfaces. These are just examples of what is possible when customizing the editor:
 
Before events to add more validation consider the following:
 

Special IEditEvents2 methods

Three methods exist on the IEditEvents2 interface that require the IEditSketch2 interface to manipulate the edit sketch rather than the user manually moving or deleting the vertex. IEditSketch2 has three functions that fire event notifications when vertices are added, modified, or deleted. Therefore, the client machine must broadcast the VertexDeleted method for the OnVertexDeleted event to fire and implement the custom code in the handler. The following discusses these three funtions:
 
Operation events not related to the sketch include the following:

Added events that fire as a result of COGO functionality

The following describes IEditEvents4 added events that fire as a result of new COGO functionality and deals with specific events:

EditToolEvents

The IEditToolEvents interface adds three more events that you can listen for when working with the editor. These events, which are specific to the edit tool and its interaction in the map, include OnBeginMove, OnFinishMove, and OnMove. The frequency at which these events fire may require the DelayEvents method to be considered.

Getting started

To get started, make sure you have an editor object, which requires that you have the editor namespace (using ESRI.ArcGIS.Editor). Once you have the editor object, find and declare the appropriate editor event interface that contains the event or events you want to listen for. Get the editor and cast it to the edit events interface as shown in the following code example using the extension startup method:
 
Other namespaces required to wire some of the edit events include the following:

[C#]
//Declare the editor and the edit events interface.
private IEditor m_editor;
private IEditEvents_Event m_editEvents;

public void Startup(ref object initializationData)
{
if (initializationData != null && initializationData is IEditor)
{
  
   m_editor = (IEditor)initializationData;
}

 //Cast the events interface to the editor.
 m_editEvents = (IEditEvents_Event)m_editor;

 //Wire edit events OnStartEditing.
  m_editEvents.OnStartEditing += new IEditEvents_OnStartEditing(
 m_editEvents_OnStartEditing);
}

[VB.NET]
'Declare the editor and the edit event interface.
Private m_editor As IEditor
Private m_editEvents As IEditEvents_Event

'Use the extension to get the editor.
Public Sub Startup(ByRef initializationData As Object) Implements IExtension.Startup
If Not initializationData Is Nothing AndAlso TypeOf initializationData Is IEditor Then  
m_editor = CType(initializationData, IEditor)

'Cast the editor to the edit events interface.
m_editEvents = CType(m_editor, IEditEvents_Event)

'Wire editor events.
AddHandler m_editEvents.OnStartEditing, AddressOf m_editEvents_OnStartEditing
End If
End Sub

Wire the event with the appropriate event interface

Now that you have the IEditEvents_Event object, you can wire the events into the appropriate event handlers. As soon as the editor is obtained, it makes sense to start listening for the start editing event. This is demonstrated in the previous code example.
 
In the previous C# code example, notice that the statement uses the += operator, and in the VB .NET code example, the AddHandler keyword is used. It is convenient that Visual Studio's IntelliSense completes the statement after you type the += operator.  

Register the handler method to the event

This step is where you provide the implementations for the event handlers. You can rely on the events to execute your custom code. When these features are selected, the target layer is changed or a vertex is moved. This is because the handler method is called when the event is fired. The handler method signature must be identical to the name of the event it is listening to. See the following code example:
 

[C#]
/Event handler method that wires two more edit events. 
private void m_editEvents_OnStartEditing()
{
 m_editEvents.OnChangeFeature += new IEditEvents_OnChangeFeatureEventHandler(
 m_editEvents_OnChangeFeature);
 m_editEvents.OnCreateFeature += new IEditEvents_OnCreateFeatureEventHandler(
 m_editEvents_OnCreateFeature);
}

[VB.NET]
'Event handler method that wires two more edit events. 
Private Sub m_editEvents_OnStartEditing()  
 AddHandler m_editEvents.OnChangeFeature, AddressOf m_editEvents_OnChangeFeature
 AddHandler m_editEvents.OnCreateFeature, AddressOf m_editEvents_OnCreateFeature
End Sub

[C#]
/// This code demonstrates how to trap for events that are triggered within the 
/// editor environment.

public class EventTrapper
{
private IEditor m_editor;
private IEditEvents_Event m_editorEvents;
private IEditEvents2_Event m_editorEvents2;

public EventTrapper(IEditor editor)
{
  m_editor = editor;
  if (m_editor == null)
    return;
  m_editorEvents = m_editor as IEditEvents_Event;
  m_editorEvents2 = m_editor as IEditEvents2_Event;

  //Set up and register delegates.

  m_editEvents.OnCurrentLayerChanged += new 
  IEditEvents_OnCurrentLayerChangedEventHandler(m_editEvents_OnCurrentLayerChanged);

  m_editEvents.OnSelectionChanged +=new 
  IEditEvents_OnSelectionChangedEventHandler(m_editEvents_OnSelectionChanged);

 m_editorEvents2.OnVertexMoved += new 
  IEditEvents2_OnVertexMovedEventHandler(m_editorEvents2_OnVertexMoved);}

public void m_editEvents_OnCurrentLayerChanged()
{
IEditLayers editLayer = m_editor as IEditLayers;
System.Windows.Forms.MessageBox.Show("Current Layer Name: " + editLayer.CurrentLayer.Name);
}

public void m_editEvents_OnSelectionChanged()
{
System.Windows.Forms.MessageBox.Show("Selection count: " + m_editor.SelectionCount);
}

public void m_editorEvents2_OnVertexMoved(IPoint point)
{
System.Windows.Forms.MessageBox.Show("New Coordinates: X = " + point.X + " Y = " + point.Y);
}

}

[VB.NET]
Public Class EventTrapper
Private m_editor As IEditor
Private m_editEvents As IEditEvents_Event
Private m_editEvents2 As IEditEvents2_Event
Public sub eventtrapper(m_editor as IEditor)
If m_editor Is Nothing Then
 Return 
End If

'Wire editor events.
m_editEvents = CType(m_editor, IEditEvents_Event)  
AddHandler m_editEvents.OnCurrentLayerChanged, AddressOf m_editEvents_OnCurrentLayerChanged
AddHandler m_editEvents.OnSelectionChanged, Addressof m_editEvents_OnSelectionChanged
AddHandler m_editEvents2.OnVertexMoved, AddressOf m_editEvents_OnVertexMoved
End Sub
Private Sub m_editEvents_OnCurrentLayerChanged()
Dim editLayer As IEditLayers = CType(m_editor, IEditLayers)
System.Windows.Forms.MessageBox.Show("Current Layer Name: " + editLayer.CurrentLayer.Name)
End Sub
Private Sub m_editEvents_OnSelectionChanged()
System.Windows.Forms.MessageBox.Show("Selection count: " + m_editor.SelectionCount)
End Sub
Private Sub m_editEvents2_OnVertexMoved(ByVal point As IPoint)
System.Windows.Forms.MessageBox.Show("New Coordinates: X = " + point.X + " Y = " + point.Y)
End Sub
End Class

WithEvents statement as best option (VB .NET only)

The WithEvents statement refers to an instance of a class that can raise events. These events are handled by a procedure that has the Handles statement. This method is easy to implement and can be the best practice in many cases, with some of the following limitations that wiring editor events are most likely not affected by:
 
See the following code example:
 

[VB.NET]
Private Sub editorEvents_OnStartEditing() Handles editorEvents.OnStartEditing
'Handle the event.
End Sub

Private m_application As IApplication
Private m_mxDoc As IMxDocument
Private m_Point As IPoint
Private m_cmdEnabled As Boolean
Private WithEvents editorEvents As Editor
Private m_editLayers As IEditLayers
Private m_editSketch As IEditSketch2
Private m_lineFeedback As INewLineFeedback
Private m_ScreenDisplay As IScreenDisplay

Public Sub New()
... 'Set up all the tool's properties.
End Sub

Public Overrides ReadOnly Property Enabled() As Boolean
Get 
 Return m_cmdenabled
End Get
End Property

'Get the editor and cast the editorEvents variable to the editor.
Public Overrides Sub OnCreate(ByVal hook As Object)
m_application = CType(hook, IApplication) 
  m_mxDoc = m_application.Document
Dim uid As New ESRI.ArcGIS.esriSystem.UID
uid.Value = "esriEditor.Editor"
Dim editor As ESRI.ArcGIS.Editor.IEditor 
  editor = CType(m_application.FindExtensionByCLSID(uid), IEditor)
editorEvents = editor
m_editLayers = CType(editor, IEditLayers)
m_editSketch = editor
m_ScreenDisplay = m_mxDoc.ActiveView.ScreenDisplay
End Sub

Public Overrides Sub OnMouseDown(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Integer, ByVal Y As Integer)
'Adds the new point in the polyline sketch when clicked.
'Get the current mouse location in map units.
Dim pPnt As IPoint
pPnt = m_ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y)
If m_lineFeedback Is Nothing Then
m_lineFeedback = New NewLineFeedback 'Create a new feedback object.
m_lineFeedback.Display = m_ScreenDisplay 'Set the feedback's display.
'Add the point to the lineFeedback.
m_lineFeedback.Start(pPnt)
End If 
m_lineFeedback.AddPoint(pPnt)
End Sub

Public Overrides Sub OnMouseMove(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Integer, ByVal Y As Integer)
If Not m_ScreenDisplay Is Nothing Then
Dim pPnt As IPoint
'Move the feedback to the current mouse location.
pPnt = m_ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y)
m_lineFeedback.MoveTo(pPnt)
End If 
End Sub

Public Overrides Sub OnDblClick()
... 'Some code implemented to get the geometry and set it to the new polyline.
End Sub

Private Sub editorEvents_OnCurrentLayerChanged() Handles editorEvents.OnCurrentLayerChanged
' Exit if there is no target (current) layer.
If m_editLayers.CurrentLayer Is Nothing Then Exit Sub
' Check that the target layer is a point layer and if it is not,
' set the edit sketch geometry type to null; this will disable the sketch tools.
If Not m_editLayers.CurrentLayer.FeatureClass.ShapeType = esriGeometryType.esriGeometryPoint Then
m_editSketch.GeometryType = esriGeometryType.esriGeometryNull
Else
m_editSketch.GeometryType = esriGeometryType.esriGeometryPoint
End If
End Sub

Private Sub editorEvents_OnSketchFinished() Handles editorEvents.OnSketchFinished
' This will update the specified field with the input box value that gets prompted during this event.
Dim editor As IEditor
editor = editorEvents
Dim fws As IFeatureWorkspace
fws = editor.EditWorkspace
Dim table As ITable
table = fws.OpenTable("Updates")
Dim s As String
s = InputBox("Enter value")
Dim row As IRow
row = table.CreateRow
row.Value(table.FindField("UpdatedValue")) = s
row.Store()
End Sub

Private Sub editorEvents_OnStartEditing() Handles editorEvents.OnStartEditing
m_cmdEnabled = True
End Sub

Private Sub editorEvents_OnStopEditing(ByVal save As Boolean) Handles editorEvents.OnStopEditing
m_cmdEnabled = False
End Sub

End Class