ObjectModified Event Handler

ObjectModified Event Handler

Anonymous
Not applicable
4,622 Views
14 Replies
Message 1 of 15

ObjectModified Event Handler

Anonymous
Not applicable
I am writing a C# program to monitor the blocks that are inserted on a specific layer (PIDSYM) and that have an attribute Tag attached called "DEVICE_NAME". I need to know when a given blocks attribute values have been modified. I have added a couple of Event Handlers to DocumentManager_DocumentActivated. The ObjectAppended event works fine, but when I put the ObjectModified event handler in the code below in it goes into an infinite loop and displays the MessageBox statement over and over. I have to kill AutoCAD to get out of the loop.
Here is the code (The attachment contains the code as well in case the {code} tags don't take):

{code}
private void DocumentManager_DocumentActivated(object sender, Autodesk.AutoCAD.ApplicationServices.DocumentCollectionEventArgs e)
{
//Get a reference to the current document's database
Database activeDatabase = AcadApp.DocumentManager.MdiActiveDocument.Database;

//Add the event handler
activeDatabase.ObjectModified += new ObjectEventHandler(OnObjectModified);
}


private void OnObjectModified(object sender, ObjectEventArgs e)
{
//If the object is already open for write then some other
//process has it so quit until it is done
if (e.DBObject.IsWriteEnabled) return;

//Is the object modified a block
if (e.DBObject is BlockReference)
{
//Set up a reference to the current drawing's database
Database db = AcadApp.DocumentManager.MdiActiveDocument.Database;

//Set up a transaction envelope and START it
using (Transaction tm = db.TransactionManager.StartTransaction())
{
try
{
//Create a reference to the block object passed in
BlockReference blkRef = e.DBObject as BlockReference;

//Open it for reading
blkRef.UpgradeOpen();

//Is it on the PIDSYM layer, if not ignore it
if (blkRef.Layer.Equals("PIDSYM"))
{
//Get the attributes off of the block reference
Autodesk.AutoCAD.DatabaseServices.AttributeCollection blockAttrs = blkRef.AttributeCollection;

//Only want the blocks that have DEVICE_NAME as the first tag
//Set up a reference to the first objectID in the list and open it for reading
AttributeReference attFirst = (AttributeReference)tm.GetObject(blockAttrs[0], OpenMode.ForRead);

//Check the attribute reference tag
if (attFirst.Tag.Equals("DEVICE_NAME"))
{
//Need a var to put the block data into
String attributeData = "";

//Cycle through the attribute objectIDs
foreach (ObjectId attrID in blockAttrs)
{
//Create a reference to the attribute and open it for reading
AttributeReference attRefers = (AttributeReference)tm.GetObject(attrID, OpenMode.ForRead);

//Append the data fields together
attributeData += attRefers.TextString + "|";

} //End foreach attrID


MessageBox.Show("Modified Block: " + attributeData);


} //End If attFirst

} //End If blkRef
}
catch (System.Exception ex)
{
MessageBox.Show("Error in OnObjectModified:: " + ex.ToString());
}

} //End Using Transaction tm

} //End If e.DBObject

} //End Method OnObjectModified

{code}
0 Likes
4,623 Views
14 Replies
Replies (14)
Message 2 of 15

Anonymous
Not applicable
I have determined that the Event Handler is being called twice for each AttributeReference attached to the object.
The sequence seems to be:
Select the block.
EATTEDIT on it
Go to Attribute 1 and change value
ObjectModified event handler fires for AttributeReference
ObjectModified event handler fires for AttributeReference Again!
Select OK

The questions now are:
Why does the event fire twice for each AttributeReference?
Can the BlockReference or objectId of the block the AttributeReference is in be determined from the AttributeReference?
0 Likes
Message 3 of 15

Anonymous
Not applicable
Sorry, your code is unreadable in a newsreader.

If you want to post a copy of it in an attached text file, then
those here using newsreaders might be able to help.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm


wrote in message
news:6168065@discussion.autodesk.com...
I have determined that the Event Handler is being called twice for each
AttributeReference attached to the object. The sequence seems to be: Select
the block. EATTEDIT on it Go to Attribute 1 and change value ObjectModified
event handler fires for AttributeReference ObjectModified event handler
fires for AttributeReference Again! Select OK The questions now are: Why
does the event fire twice for each AttributeReference? Can the
BlockReference or objectId of the block the AttributeReference is in be
determined from the AttributeReference?
0 Likes
Message 4 of 15

Anonymous
Not applicable
Tony,
The current code sequence is attached.

The main issue is: How do I determine what block the modified attribute is attached to?
0 Likes
Message 5 of 15

Anonymous
Not applicable
The OwnerId property of an AttributeReference holds the
ObjectId of the BlockReference.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm


wrote in message
news:6168883@discussion.autodesk.com...
Tony, The current code sequence is attached. The main issue is: How do I
determine what block the modified attribute is attached to?
0 Likes
Message 6 of 15

Anonymous
Not applicable
No, no, no....That's way too easy.

Thanks Tony.

Any idea why the ObjectModified event gets fired twice for each object that is modified?

Why would the DocumentManager_DocumentActivated event get called twice when I switch from one open drawing to another?
0 Likes
Message 7 of 15

Anonymous
Not applicable
There are plenty of circumstances where there may
be multiple modifications to an object, like for example,
a VBA macro that sets its properties (each property
that's set will trigger an ObjectModified notification).

So, you have to store the ObjectIds of the objects that
have sent the notification one or more times in a collection,
and after the operation has completed, then you act on the
collection and do your stuff.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm


wrote in message
news:6169145@discussion.autodesk.com...
No, no, no....That's way too easy. Thanks Tony. Any idea why the
ObjectModified event gets fired twice for each object that is modified? Why
would the DocumentManager_DocumentActivated event get called twice when I
switch from one open drawing to another?
0 Likes
Message 8 of 15

Anonymous
Not applicable
Originally you were asking why the 'ObjectModified' event fires more than
once for the same object.

After looking more closely at your code, the reason is because you are
adding the event handler for the ObjectModified event to the Database more
than once, and so the event fires once for each time you've added the
handler.

The mistake you're making is adding an ObjectModified event handler in the
DocumentActivated event. That event fires *every* time you switch documents
or just bring AutoCAD into the foreground, If you add the ObjectModified
event handler from that event, it will be added multipole times, every time
the document window is activated, which means that it will fire as many
times as you've added the handler.

You can only add an event handler to an event *once*. If you fail to follow
that rule, the event is going to fire multiple times (once for each time you
added the handler).

You're getting into somewhat advanced AutoCAD programming topics, way ahead
of your experience level. My advice would be to focus on more basic
programming tasks to become more familar with not only the AutoCAD API, but
the programming tools you're using, and more specifically, how events and
event handlers work.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm


wrote in message
news:6169145@discussion.autodesk.com...
No, no, no....That's way too easy. Thanks Tony. Any idea why the
ObjectModified event gets fired twice for each object that is modified? Why
would the DocumentManager_DocumentActivated event get called twice when I
switch from one open drawing to another?
0 Likes
Message 9 of 15

Anonymous
Not applicable
I have so far managed to create an app that:
1. Reads the block data from a given drawing,
2. Then queries and returns the attribute data in a set of Oracle tables that are associated with the same drawing number.
3. Combines the two sets of data together into a DataGridView and checks for consistency between them
4. Then parses those grid entries out into 3 other DataGridViews depending on what state each entry is in.

I need to be able to update the DataGridView data (and eventually the Oracle tables) as it is being modified by the user.
The only way I see to do that is with event handlers.

Perhaps if the AutoCAD documentation didn't suck so much I could parse my way through it.

If I can't make this data update in real-time then this whole effort is worthless and I might as well leave it in VBA.
0 Likes
Message 10 of 15

Anonymous
Not applicable
{quote}

I need to be able to update the DataGridView data (and eventually the Oracle
tables) as it is being modified by the user. The only way I see to do that
is with event handlers. Perhaps if the AutoCAD documentation didn't suck so
much I could parse my way through it. If I can't make this data update in
real-time then this whole effort is worthless and I might as well leave it
in VBA.

{quote}.

What happens if/when the user uses the UNDO function to undo changes they've
made? Go back to the database and change it again? And, why does the data
need to be updated in 'real-time' rather than at the point when the drawing
file is saved?

I generally do not advise that one try to keep data synchronized between an
open DWG and an external data source, because there are numerous issues
related to doing that, some of which you may not have considered. I don't
think any documentation no matter how good it is, is going to explain all of
that.

Also, the problem you had isn't something you can blame on Autodesk's
documentation. Knowing that adding the same handler to the same event
multiple causes the event to fire as many times, is .NET programming 101.

As far as adding the ObjectModified event handler in the DocumentActivated
event, I don't think it's unreasonable for someone to understand that the
event fires many times, not just once, and you shoudn't need docs to
understand that.

You can add the ObjectModified event handler from within a handler of the
DocumentCollection's DocumentAdded event, which only fires once for each
DWG, when it is opened.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm


wrote in message
news:6170262@discussion.autodesk.com...
I have so far managed to create an app that: 1. Reads the block data from a
given drawing, 2. Then queries and returns the attribute data in a set of
Oracle tables that are associated with the same drawing number. 3. Combines
the two sets of data together into a DataGridView and checks for consistency
between them 4. Then parses those grid entries out into 3 other
DataGridViews depending on what state each entry is in. I need to be able to
update the DataGridView data (and eventually the Oracle tables) as it is
being modified by the user. The only way I see to do that is with event
handlers. Perhaps if the AutoCAD documentation didn't suck so much I could
parse my way through it. If I can't make this data update in real-time then
this whole effort is worthless and I might as well leave it in VBA.
0 Likes
Message 11 of 15

Anonymous
Not applicable
In the VBA version of this program, I watch for the EATTEDT command and when it completes I execute a Sub that writes the new data into the database. I am only doing this for Device blocks that are placed on a specific layer and that have a specific set of attributes. Everything else is ignored. The only reason I am not updating the display grids along with the database is that the VBA app won't run in tandem with AutoCAD. So everytime the user opens the Device Data dialog I run a synch Sub that queries the database, refreshes the data and updates the display grid. This has worked fine for the past year. All I want to do now is have the Device Data grid open all the time for reference and update it's contents as needed.

As for Undo/Redo/Copy - don't really care because the next time a Device Data dialog is opened the synch takes place and those Devices are flagged as errors/duplicates until another EATTEDIT updates them again.

As for documentation - where is it written that the "DocumentCollection's DocumentAdded event only fires once for each DWG, when it is opened."

Seems odd that I can do all these complex functions in VBA, but can't replicate them in C#.
0 Likes
Message 12 of 15

Anonymous
Not applicable
"As for documentation - where is it written that the "DocumentCollection's
DocumentAdded event only fires once for each DWG, when it is opened." Seems
odd that I can do all these complex functions in VBA, but can't replicate
them in C#."

Why would it need to explicitly say that, when it is implied?

When you open a drawing file, the DocumentAdded event fires, signaling that
another document has been added to the documents collection. Doesn't it just
take a little common sense to realize that this event would not fire more
than once for a given document?

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm


wrote in message
news:6170953@discussion.autodesk.com...
In the VBA version of this program, I watch for the EATTEDT command and when
it completes I execute a Sub that writes the new data into the database. I
am only doing this for Device blocks that are placed on a specific layer and
that have a specific set of attributes. Everything else is ignored. The only
reason I am not updating the display grids along with the database is that
the VBA app won't run in tandem with AutoCAD. So everytime the user opens
the Device Data dialog I run a synch Sub that queries the database,
refreshes the data and updates the display grid. This has worked fine for
the past year. All I want to do now is have the Device Data grid open all
the time for reference and update it's contents as needed. As for
Undo/Redo/Copy - don't really care because the next time a Device Data
dialog is opened the synch takes place and those Devices are flagged as
errors/duplicates until another EATTEDIT updates them again. As for
documentation - where is it written that the "DocumentCollection's
DocumentAdded event only fires once for each DWG, when it is opened." Seems
odd that I can do all these complex functions in VBA, but can't replicate
them in C#.
0 Likes
Message 13 of 15

Anonymous
Not applicable
{quote}

Seems odd that I can do all these complex functions in VBA, but can't
replicate them in C#.

{quote}

Anything you can do in VBA can be done in C# , provided you're familar with
the language and API.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm


wrote in message
news:6170953@discussion.autodesk.com...
In the VBA version of this program, I watch for the EATTEDT command and when
it completes I execute a Sub that writes the new data into the database. I
am only doing this for Device blocks that are placed on a specific layer and
that have a specific set of attributes. Everything else is ignored. The only
reason I am not updating the display grids along with the database is that
the VBA app won't run in tandem with AutoCAD. So everytime the user opens
the Device Data dialog I run a synch Sub that queries the database,
refreshes the data and updates the display grid. This has worked fine for
the past year. All I want to do now is have the Device Data grid open all
the time for reference and update it's contents as needed. As for
Undo/Redo/Copy - don't really care because the next time a Device Data
dialog is opened the synch takes place and those Devices are flagged as
errors/duplicates until another EATTEDIT updates them again. As for
documentation - where is it written that the "DocumentCollection's
DocumentAdded event only fires once for each DWG, when it is opened." Seems
odd that I can do all these complex functions in VBA, but can't replicate
them in C#.
0 Likes
Message 14 of 15

Anonymous
Not applicable
" When you open a drawing file, the DocumentAdded event fires, signaling that another document has been added to the documents collection. Doesn't it just take a little common sense to realize that this event would not fire more than once for a given document?"

There is no DocumentAdded event.
Perhaps you meant DocumentActivated?
0 Likes
Message 15 of 15

Anonymous
Not applicable
Sorry, no I meant DocumentCreated, not DocumentAdded, but come to mention
it, if you made the investement in becoming reasonably familar with the API
and
specifically, the DocumentCollection class, you probably woudln't have had
to ask this, and probably wouldn't be having the problems you're had.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm


wrote in message
news:6172056@discussion.autodesk.com...
" When you open a drawing file, the DocumentAdded event fires, signaling
that another document has been added to the documents collection. Doesn't it
just take a little common sense to realize that this event would not fire
more than once for a given document?" There is no DocumentAdded event.
Perhaps you meant DocumentActivated?
0 Likes