Detect Table of Contents Changes in ArcMap using ArcObjects?
You can use the IActiveViewEvents handler to determine when an item is added or removed from the TOC. In this example clsPropSet.Document is an IMxDocument ref and clsPropSet.Map is an IMap ref.
private static IDocumentEvents_CloseDocumentEventHandler cdHandler;
private static IActiveViewEvents_ItemAddedEventHandler iaHandler;
private static IActiveViewEvents_ItemDeletedEventHandler idHandler;
internal void SetupEvents()
{
//HANDLE THE FOLLOWING EVENTS
cdHandler = new IDocumentEvents_CloseDocumentEventHandler(OnDocClose);
((IDocumentEvents_Event)clsPropSet.Document).CloseDocument += cdHandler;
iaHandler = new IActiveViewEvents_ItemAddedEventHandler(OnActiveViewEventsItemAdded);
((IActiveViewEvents_Event)clsPropSet.Map).ItemAdded += iaHandler;
idHandler = new IActiveViewEvents_ItemDeletedEventHandler(OnActiveViewEventsItemDeleted);
((IActiveViewEvents_Event)clsPropSet.Map).ItemDeleted += idHandler;
}
internal void UnloadEvents()
{
((IDocumentEvents_Event)clsPropSet.Document).CloseDocument -= cdHandler;
((IActiveViewEvents_Event)clsPropSet.Map).ItemAdded -= iaHandler;
((IActiveViewEvents_Event)clsPropSet.Map).ItemDeleted -= idHandler;
}
private void OnDocClose()
{
//DO SOMETHING WHEN DOCUMENT CLOSES
}
private void OnActiveViewEventsItemAdded(object Item)
{
//DO SOMETHING WHEN ITEM ADDED
}
private void OnActiveViewEventsItemDeleted(object Item)
{
//DO SOMETHING WHEN ITEM REMOVED
}
There are a number of events you can subscribe to in order to do something when the map's contents change, items are added, reordered or removed, the maps collection changes, the map document is opened, saved, or closed, etc.
One thing that tripped me up was when I was trying to determine when a broken-data-source feature class's data source changes, which led me to use IActiveViewEvents.ContentsChanged
as a general purpose catch-all. It will tell you when something changes, just not what changed. I am not sure if it will catch when things are added, removed or reordered in the TOC, since there are explicit events for those, so be sure to test.
Depending on what you are trying to do and whether you need to keep track of certain things, you could continue using a dictionary and just update it/run through your logic whenever those events fire. I would consider using a layer object's HashCode
as a key instead of Name
though since Name
is not guaranteed to be unique and is actually liable to be changed by the user. Unfortunately ArcObjects provides no persistent unique layer identifier (in desktop at least, I think on the server side they do), so HashCode
is about the best you can do.
You'll need to wire up multiple events starting with Open/NewDocument events in which you wire up your active view event handler(s) -- one for the FocusMap and one for the PageLayout as they receive different events -- as whenever the current document or active data frame is changed existing active view event handlers will become invalid. To be safe add one for CloseDocument where you unwire your active view event handlers.
Check the samples for examples of these as it can be tricky to get right.