Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

Is there an interface which exposes events for when a TOC selected item changes?

I can find snippets showing how to get the currently selected feature from the TOC. However, I have not been able to find anything that allows you to track when a selection changes - only query the current state.

What would be the best approach (preferably other than polling) to track the user's current layer selected within ArcMap and ArcScene?

share|improve this question
add comment

4 Answers

up vote 6 down vote accepted

There is indeed no appropriate event. As described in links in another post, people have worked around this by polling for the state in a command's Enabled() method, which gets called very often by the framework. But this of course assumes you do have a command and fails when the command is not on any toolbars or top-level menus, in which case Enabled() does not get called or gets called only on demand.

In the past, I remember "solving" this problem by hooking into the display contents view (i.e. TOC) window procedure, intercepting mouse and keyboard messages and tracking if the selection changed. Terrible hack, but worked. If you're interested, I'll port it to .NET and post here, but as I said and will say again, it is a very ugly workaround.

share|improve this answer
    
k. I'm interested –  patrick Nov 20 '10 at 18:27
    
Ok, I'll post the code sample as soon as I get round to it later this week. –  Petr Krebs Nov 22 '10 at 21:24
add comment

I would like to confirm that there is indeed no appropriate event. As Petr Krebs mentioned you could workaround this limitation by hooking into the display contents view (ESRI.ArcGIS.ArcMapUI.IMxDocument.ContentsView) window procedure, intercepting mouse and keyboard messages and tracking if the selection changed.

Back in 2004 Kirk Kuykendall already suggested a possible solution process in the ArcGIS Desktop Discussion Forums:

The only way I know of doing this is to subclass IContentsView.hWnd and trap the WM_RBUTTONUP message.

I think the layer gets selected in the WM_MOUSEDOWN event, so by the time you get a mouseup IMxDocument.SelectedItem should already be set to whatever the user has clicked on.

I tried that using ArcObjects SDK for .NET v10 for ArcMap 10.1 but it seems that a layer doesn't get selected in the WM_LBUTTONDOWN event. Thats true for WM_RBUTTONDOWN and even for WM_RBUTTONUP or WM_LBUTTONUP. Also if you are using the subclassing approach it seems that some of the mouse events are eaten up by the SysTreeView32 component which displays the TOC contents.

Digging a bit deeper using Spy++ I came up with the idea to hook in to the SysTreeView32 component directly and listening for the Tree View Notification TVN_SELCHANGED:

Spy++ investigation on SysTreeView32

This approach is working for me very well. I put together an example and put it up on Bitbucket:

https://bitbucket.org/christianjunk/arcobjects-sdk-for-.net-samples

share|improve this answer
add comment

I don't know of an event for this and I have had to use the method @Petr k. describes in his answer.

For the Addin, you would use OnUpdate to accomplish the same thing:

http://code.google.com/p/umbriel/source/browse/trunk/Umbriel.ArcMap.Addin/Umbriel.ArcMap.Addin.OneSelectableLayer/OneSelectableLayerButton.cs#94

share|improve this answer
add comment

The class TOCDisplayView, which displays the list of layers in ArcMap, is supposed to implement the interface IActiveViewEvents. It does, but it doesn't seem to implement the .NET equivalent IActiveViewEvents_Event which means that I'm unable to catch said events. I can only test this with ArcGIS 9.3 and maybe they added that in 10.0 but I doubt that. In theory IActiveViewEvents.SelectionChanged should be doing what you're looking for. You can obtain a reference to the TOCDisplayView object by

IApplication app = GetFromSomewhere();
IMxDocument doc = app.Document as IMXDocument;
if(doc.CurrentContentsView is TOCDisplayView) {
    IActiveViewEvents_Event events = doc.CurrentContentsView as IActiveViewEvents_Event
}

But the object 'events' will always be NULL, which means that you won't be able to catch an event of the type you described. This problem seems to be hanging around for some time now because there are a lot of threads regarding that in the old ESRI forums. Here's a description of a workaround, see link1 and link2.

share|improve this answer
1  
It implements the interface as an inbound interface, which means it listens to the exposed events, not an outbound interface which would allow you to subscribe to them. Not sure why in some cases like this, the documentation mentions inbound event interfaces as it is simply an implementation detail. –  Petr Krebs Nov 20 '10 at 11:26
1  
The more I use wpf/silverlight the more I wonder when Esri will port desktop apps to wpf. This sort of event wiring sure would be a lot more manageable. –  Kirk Kuykendall Nov 20 '10 at 15:08
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.