Author Topic: Adding an ObjectEventHandler  (Read 2275 times)

0 Members and 1 Guest are viewing this topic.

Keith Brown

  • Swamp Rat
  • Posts: 601
Adding an ObjectEventHandler
« on: November 05, 2012, 10:47:50 PM »
I have created an ObjectEventHandler that will add information to certain objects.  I currently invoke it with a command but plan to move it to my initialize routine.  The problem I noticed is that if i create a new document the event handler does not work.  Should I instead create an event handler for document open and add my ObjectEventHandler to it?  I thought I read somewhere that you should not call an Eventhander from another EventHandler.  What would be the proper way to address this situation and make sure that my ObjectEventHander will always fire? 
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

Keith Brown

  • Swamp Rat
  • Posts: 601
Re: Adding an ObjectEventHandler
« Reply #1 on: November 06, 2012, 08:10:42 AM »
So below is what I have that is working for the current database and any new databases that are added.  It is not working for any databases that are currently opened.  Any ideas on what to try next?  If the plugin is designed to run when autocad starts should I worry about any databases that are currently opened?  I know that answer to that question should be yes but I was just wondering.

Code - C#: [Select]
  1.     [CommandMethod("addhandler")]
  2.     public void AddHandler()
  3.     {
  4.         Database db = HostApplicationServices.WorkingDatabase;
  5.         DocumentCollection acDocs = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager;
  6.  
  7.         // Add the event handler for each opened document
  8.         foreach (Document doc in acDocs)
  9.         {
  10.             db.ObjectAppended += new ObjectEventHandler(callback_ObjectAppended);
  11.         }
  12.  
  13.         // Ad the event handler for any newly created documents
  14.         acDocs.DocumentCreated += new DocumentCollectionEventHandler(callback_DocumentCreated);
  15.     }
  16.  
  17.     private void callback_DocumentCreated(object sender, DocumentCollectionEventArgs e)
  18.     {
  19.         Database db = HostApplicationServices.WorkingDatabase;
  20.  
  21.         // Add the object appended event hander to any newly created database
  22.         db.ObjectAppended += new ObjectEventHandler(callback_ObjectAppended);
  23.     }
  24.  
  25.     private void callback_ObjectAppended(object sender, ObjectEventArgs e)
  26.     {
  27.           //  Do something here.
  28.     }
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

BlackBox

  • King Gator
  • Posts: 3770
Re: Adding an ObjectEventHandler
« Reply #2 on: November 06, 2012, 08:35:28 AM »
Depending on how you want your application to load, you might add a call to AddHandler(), or SendStringToExecute("addhandler\n", false, false, true) via Initialize().

You might also want to consider per-document data, albeit in the small form of simply tracking which Document has already had the Object event handler added (i.e., a Loaded Property?).
"How we think determines what we do, and what we do determines what we get."

BlackBox

  • King Gator
  • Posts: 3770
Re: Adding an ObjectEventHandler
« Reply #3 on: November 06, 2012, 08:38:23 AM »
Also, out of curiosity, is there a reason that you use HostApplicationServices.WorkingDatabase within your callback_DocumentCreated() Method in lieu of e.Document.Database?
"How we think determines what we do, and what we do determines what we get."

Keith Brown

  • Swamp Rat
  • Posts: 601
Re: Adding an ObjectEventHandler
« Reply #4 on: November 06, 2012, 09:00:43 AM »
That was a cut/paste error.  oops!!  I did change that particular error (although it did work) and changed the declaration inside of my command also.  I need to read up on it because I currently do not understand enough of the differences between the different declarations.  Below is the code as I currently have it.  The ObjectAppended event handler will work for the current document and any newly created documents but will not work for any documents already opened other than the current one.  It is my intention to move the code into my initialize routine and forego the command once I get it running.  As I mentioned before, maybe this whole conversation is mute if I do put it in the initialize routine and make sure it runs when Autocad loads.  It just seems like a hokey way to bypass an error in the code.

Code - C#: [Select]
  1.  
  2.     [CommandMethod("addhandler")]
  3.     public void AddHandler()
  4.     {
  5.         Database db = Application.DocumentManager.MdiActiveDocument.Database;
  6.         DocumentCollection acDocs = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager;
  7.        
  8.         // Add the event handler for each opened document
  9.         foreach (Document doc in acDocs)
  10.         {
  11.             db.ObjectAppended += new ObjectEventHandler(callback_ObjectAppended);
  12.         }
  13.  
  14.         // Add the event handler for any newly created documents
  15.         acDocs.DocumentCreated += new DocumentCollectionEventHandler(callback_DocumentCreated);
  16.     }
  17.  
  18.     private void callback_DocumentCreated(object sender, DocumentCollectionEventArgs e)
  19.     {
  20.         Database db = e.Document.Database;
  21.  
  22.         db.ObjectAppended += new ObjectEventHandler(callback_ObjectAppended);
  23.     }
  24.  
  25.     private void callback_ObjectAppended(object sender, ObjectEventArgs e)
  26.     {
  27.           // Do something here
  28.     }
« Last Edit: November 06, 2012, 09:04:15 AM by Keith Brown »
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

Jeff H

  • Needs a day job
  • Posts: 6151
Re: Adding an ObjectEventHandler
« Reply #5 on: November 06, 2012, 09:53:35 AM »
That was a cut/paste error.  oops!!  I did change that particular error (although it did work) and changed the declaration inside of my command also.  I need to read up on it because I currently do not understand enough of the differences between the different declarations.  Below is the code as I currently have it.  The ObjectAppended event handler will work for the current document and any newly created documents but will not work for any documents already opened other than the current one.  It is my intention to move the code into my initialize routine and forego the command once I get it running.  As I mentioned before, maybe this whole conversation is mute if I do put it in the initialize routine and make sure it runs when Autocad loads.  It just seems like a hokey way to bypass an error in the code.

Code - C#: [Select]
  1.  
  2.     [CommandMethod("addhandler")]
  3.     public void AddHandler()
  4.     {
  5.         Database db = Application.DocumentManager.MdiActiveDocument.Database;
  6.         DocumentCollection acDocs = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager;
  7.        
  8.         // Add the event handler for each opened document
  9.         foreach (Document doc in acDocs)
  10.         {
  11.             db.ObjectAppended += new ObjectEventHandler(callback_ObjectAppended);
  12.         }
  13.  
  14.         // Add the event handler for any newly created documents
  15.         acDocs.DocumentCreated += new DocumentCollectionEventHandler(callback_DocumentCreated);
  16.     }
  17.  
  18.     private void callback_DocumentCreated(object sender, DocumentCollectionEventArgs e)
  19.     {
  20.         Database db = e.Document.Database;
  21.  
  22.         db.ObjectAppended += new ObjectEventHandler(callback_ObjectAppended);
  23.     }
  24.  
  25.     private void callback_ObjectAppended(object sender, ObjectEventArgs e)
  26.     {
  27.           // Do something here
  28.     }

If you look you get the database of the current document then loop through the documents add the ObjectAppended event to same database.
So if you got 5 docs you add the event to same database.
 
About to walk out door and would probably be better to keep events per doc and database in seperate class but do you see the difference in this
Code - C#: [Select]
  1. DocumentCollection acDocs = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager;
  2.  
  3. // Add the event handler for each opened document
  4. foreach (Document doc in acDocs)
  5. {
  6. doc.Database.ObjectAppended += new ObjectEventHandler(callback_ObjectAppended);
  7. }
  8.  
  9.  

BlackBox

  • King Gator
  • Posts: 3770
Re: Adding an ObjectEventHandler
« Reply #6 on: November 06, 2012, 10:01:42 AM »
I completely overlooked db.ObjectAppended in the AddHandler() Method's foreach loop (oops!) :lol:

Jeff is correct, my apps also use doc.Database.<SomeEvent> when iterating the DocumentManager.
"How we think determines what we do, and what we do determines what we get."

Keith Brown

  • Swamp Rat
  • Posts: 601
Re: Adding an ObjectEventHandler
« Reply #7 on: November 06, 2012, 11:10:41 AM »
Jeff,

That was exactly the explanation and solution I was looking for! Thanks again.  It now works beautifully and for the bigger picture I will add the command to my initialize routine and have it run when Autocad MEP starts.

Sometimes i think it takes hurdles like this to really learn how to really use the api and to modify my way of thinking.  I was thinking I just needed to add the event handler to the database when I should have been thinking I needed to add the event handler to each documents database.  A mistake that I will not make again.  Cheers.
Keith Brown | AutoCAD MEP Blog | RSS Feed
AutoCAD MEP 2014 / Revit MEP 2014 / EastCoast CAD/CAM addon / Visual Studio 2013

TheMaster

  • Guest
Re: Adding an ObjectEventHandler
« Reply #8 on: November 08, 2012, 09:43:56 AM »
Jeff,

That was exactly the explanation and solution I was looking for! Thanks again.  It now works beautifully and for the bigger picture I will add the command to my initialize routine and have it run when Autocad MEP starts.

Sometimes i think it takes hurdles like this to really learn how to really use the api and to modify my way of thinking.  I was thinking I just needed to add the event handler to the database when I should have been thinking I needed to add the event handler to each documents database.  A mistake that I will not make again.  Cheers.

You'll also find that making a class for which a separate instance is created for each document, and making document/editor/database event handlers instance members of that class, will in the long-run, save you more headaches, especially if  your event handlers must reference document-specific data.