A couple of times I've seen people asking about how to share information between forms/commands/tools etc. in ArcMap and I thought I'd create a simple example of how I've been doing it.
Problem
At a high level, the problem is pretty simple - one part of your application needs to know about the state of another part. One example could be a combo box tool control that allows the user to select an Active layer, and you have other tools/controls/forms etc that need to know what the active layer is, and need to be informed when the active layer changes.
Solution
This is an obvious case where custom events are going to come into play, since they are the standard way to provide notification of a state change to a set of "subscribing" or listening classes. In standard .NET applications, you'd create an event right on the actual source - in this case the tool control. However, since we are working in ArcMap, we have a slightly different situation. Since we (developers) do not control the load order of tools/commands etc in ArcMap, it's rather difficult to effectively sink up event handlers and sources if they are all located in your customization classes (ICommand/ITool etc). This is because we don't really know when either class is actually instantiated during the load process, and once it's instantiated, it's a pain to actually get a pointer to it.
The way to solve this is to route the events through something that's always loaded, and easily accessed - such as an application extension (IExtension).
Since application extensions (with the exception of JIT Extensions) are always loaded when ArcMap is starting up, we know it's always present. Regardless of when the event source tool / form / command is initialized, it will always be able to call a method on the extension, which then raises an event. The same it true for the classes handling the event - since the extension is loaded and accessible, they can wire up an event handler during their initialization, or any time after that.
While there are other ways to pass "state" around, using an event allows a whole set of classes to then subscribe to the event and be notified when changes occur.
Once you think about it, this is quite obvious, and it is a small scale mirror of much of the ArcObjects customization API - write a class, wire it into ArcMap, and have it respond to ArcMap events. Except in this case, it's our own custom event.
Sample
The sample is in C#, and is kept very simple, so the focus is on wiring the events.
Extension:
The extension has a public SetSelectedItem method, which in turn raises the SelectedItemChanged event.
Commands:
There are two commands - EventSourceCommand and EventSinkCommand. In the onCreate function, both commands get pointers to the event extension, and pass this into the IntializeUI methods on the forms. The Event Source Form has a simple combo box listing 5 fruits. In the OnChange event of the combo box, the form calls SetSelectedItem on the extension. The Extension raises the SelectedItemChanged event, to which the Event Sink Form has subscribed, and a label is updated to show the currently selected fruit. Although it's a bit complex when you read it, this is very simple when you look at the code, and run it.
Since the sample is in C#, it uses event wiring involving delegates. If you are new to delegates, O'Reilly has a good article - Writing C# Custom Events, which I would recommend. The syntax is much simpler in VB.NET, and here's a CodeProject article on that. Of course you can use delegates in VB.NET if you want to, so for completeness sake, here's an article on events using delegates in VB.NET. Moving on...
To run the sample, download the code, compile it, and run ArcMap. You should get a pop-up box as ArcMap is loading which tells you that the Event Extension is loading. Once ArcMap is started, open up the Customize dialog, and look in the DaBo.Samples category.
Drag the Event Sink and Event Source command onto a toolbar, and then run them. Both commands open forms. Use the pulldown on the Event Source Form to update the label on the Event Sink Form.
When you dig into the code you'll see that I've used the out of the box templates for the commands and extension. The only other "cool" thing I threw in was the ArcMapWindow class I wrote about previously.
Have fun wiring up your events!
Download Sample
I'm Dave and this is my blog. I'm usually writing about .NET Software Development, ArcGIS, or Agile Practices, but other stuff does creep in from time to time. I hope you find something of use, and feel free to contact me if you have any questions. You can also check out my profile on LinkedIn
dojo.DTSAgile.com is our technology preview / demo site. As I and my team cook up cool things we post them here.
ArcDeveloper.net is a site that hosts a set of open source projects related to ArcGIS. This includes Tile Cache for .NET (TC4N) and Feature Server for .NET (FS4N). Come over and check it out!
Assembla is a free service that provides Subversion source control, wikis and work Tracking. The ArcDeveloper project is run from here. It rocks. Check them out today.
Agilistas is a LinkedIn group focused on discussing and promoting Agile practices. Everyone is welcome to join in the conversation as we evolve the process of creating software to make it more enjoyable for all involved.