.NET

Reply
Active Member
soccerazy
Posts: 8
Registered: ‎10-06-2011
Message 1 of 10 (306 Views)
Accepted Solution

Add Block When Other Drawings Are Open

306 Views, 9 Replies
11-14-2011 09:39 AM

I'm trying to add a block with an attribute to a drawing. The command works if there is only one drawing open, but when there are other open drawings then the block doesn't appear. Strangely if I select the block in the block editor and then close the block editor the block suddenly appears. Do you know what is causing the block to not appear when other drawings are open?

 

I included the code below. "s1" works but "s2" has the strange behavior of the block not being visible.

 

Thanks for any help,

 

Casey Joyce

 

[CommandMethod("s1")]
public void AddBlockWithAttributeToDestination_WithNoOtherDrawingsOpen() {
    var attributeValue = "1234";
    var destination = Application.DocumentManager.MdiActiveDocument;
    using (var transaction = destination.TransactionManager.StartTransaction()) {
        addBlock(transaction, destination.Database, attributeValue);
        transaction.Commit();
    }
}

[CommandMethod("s2")]
public void AddBlockWithAttributeToDestination_WhileSourceDrawingIsOpen() {
    // pretend user selects info from opened source drawing
    var attributeValue = "1234";
    // pretend user selects destination drawing from popup list
    var destinationDrawing = @"c:\destination.dwg";

    // add block to destination drawing
    var destination = Application.DocumentManager.Open(destinationDrawing, false);
    using (var transaction = destination.TransactionManager.StartTransaction()) {
        using (var key = destination.LockDocument()) {
            addBlock(transaction, destination.Database, attributeValue);
        }
        transaction.Commit();
    }
}

void addBlock(Transaction transaction, Database database, string attributeValue) {
    // add block
    var block = new BlockTableRecord() { Name = "SampleBlock" };
    var table = transaction.GetObject(database.BlockTableId, OpenMode.ForWrite) as BlockTable;
    var blockId = table.Add(block);
    transaction.AddNewlyCreatedDBObject(block, true);
    // add block reference
    var blockReference = new BlockReference(Point3d.Origin, block.ObjectId);
    var modelSpace = transaction.GetObject(table[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
    modelSpace.AppendEntity(blockReference);
    transaction.AddNewlyCreatedDBObject(blockReference, true);

    // set attribute definition
    var definition = new AttributeDefinition(
        new Point3d(1, 1, 0),
        attributeValue,
        "SampleAttribute",
        "",
        database.Textstyle);
    block.AppendEntity(definition);
    transaction.AddNewlyCreatedDBObject(definition, true);
    // add attribute reference
    var reference = new AttributeReference();
    reference.SetAttributeFromBlock(definition, blockReference.BlockTransform);
    blockReference.AttributeCollection.AppendAttribute(reference);
    transaction.AddNewlyCreatedDBObject(reference, true);
}

I think I am going to be able to get s2 to work by adding CommandFlags.Session. So far it looks like its working.

 

[CommandMethod("s2", CommandFlags.Session)]

*Expert Elite*
GTVic
Posts: 917
Registered: ‎09-07-2004
Message 2 of 10 (291 Views)

Re: Add Block When Other Drawings Are Open

11-14-2011 03:35 PM in reply to: soccerazy

Maybe you should lock the document?

 

Using acLckDoc As DocumentLock = acNewDoc.LockDocument()

End Using
Active Member
soccerazy
Posts: 8
Registered: ‎10-06-2011
Message 3 of 10 (268 Views)

Re: Add Block When Other Drawings Are Open

11-15-2011 01:32 PM in reply to: GTVic

Thanks for your response GTVic. I am using LockDocument in the s2 command, and that's the one that wasn't working.

Active Member
soccerazy
Posts: 8
Registered: ‎10-06-2011
Message 4 of 10 (267 Views)

Re: Add Block When Other Drawings Are Open

11-15-2011 01:35 PM in reply to: soccerazy

I think I am going to be able to get s2 to work by adding CommandFlags.Session. So far it looks like its working.

 

[CommandMethod("s2", CommandFlags.Session)]

*Expert Elite*
GTVic
Posts: 917
Registered: ‎09-07-2004
Message 5 of 10 (260 Views)

Re: Add Block When Other Drawings Are Open

11-15-2011 02:15 PM in reply to: soccerazy

Sorry, didn't notice that, maybe because it was inside the transaction. I think that is a problem, the document should be locked before starting the transaction. That is the way it is documented in the Developer's Guide

 

CommandFlags.Session might mask the problem. The effect of "Session" is not clear but I take it that nothing else can happen in the application while this command is running and then perhaps there is no need for a lock and the lock being out of order doesn't cause a problem.

Active Member
soccerazy
Posts: 8
Registered: ‎10-06-2011
Message 6 of 10 (252 Views)

Re: Add Block When Other Drawings Are Open

11-15-2011 03:12 PM in reply to: GTVic

I moved the LockDocument outside the transaction as you and the Developer Guide suggested, thanks. When I keep the CommandFlags.Session this seems to work fine. So unless I find a better way I guess I'll stick with this.

 

Just FYI:

Even with the lock on the outside of the transaction, the CommandFlags.Session is still required for me to get "s2" to work.

 

I tried removing the LockDocument all together to see if CommandFlags.Session would take care of it, but it throws an exception in that case.

*Expert Elite*
GTVic
Posts: 917
Registered: ‎09-07-2004
Message 7 of 10 (247 Views)

Re: Add Block When Other Drawings Are Open

11-15-2011 03:33 PM in reply to: soccerazy

Maybe you need to lock the source drawing, if I'm understanding your code correctly.

 

This is my subroutine to copy block definitions from a template DWG to the current drawing using the clone method. I use it for updating block definitions or bringing in missing blocks.

 

    Private Sub LoadBlocks()

        Dim dm As DocumentCollection = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager
        Dim ed As Editor = dm.MdiActiveDocument.Editor
        Dim destDb As Database = dm.MdiActiveDocument.Database
        Dim sourceDb As Database = New Database(False, True)
        Dim mapping As IdMapping = New IdMapping()
        Dim blockIds As ObjectIdCollection = New ObjectIdCollection()
        Dim s As String
        Dim DisplayError As Boolean = False

        Try
            Using objLock As DocumentLock = AcadDoc.LockDocument()
                Try
                    sourceDb.ReadDwgFile(Path.Combine(Path.Combine(EngToolsPath.FullName, "Source"), cboSource.Text), System.IO.FileShare.Read, True, "")
                    Try
                        Using Trans As Transaction = sourceDb.TransactionManager.StartTransaction()
                            Try
                                Dim bt As BlockTable = Trans.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, False)
                                Dim btr As BlockTableRecord
                                For Each btrId As ObjectId In bt
                                    btr = Trans.GetObject(btrId, OpenMode.ForRead, False)
                                    If lstItems.SelectedItems.Contains(btr.Name) Then
                                        blockIds.Add(btrId)
                                    End If
                                    btr.Dispose()
                                Next
                            Catch ex As Autodesk.AutoCAD.Runtime.Exception
                                ed.WriteMessage(vbLf & "Error scanning for block definitions in source drawing: " & ex.Message & vbLf)
                                ed.UpdateScreen()
                                DisplayError = True
                            End Try
                        End Using
                    Catch ex As Autodesk.AutoCAD.Runtime.Exception
                        ed.WriteMessage(vbLf & "Error reading from source drawing: " & ex.Message & vbLf)
                        ed.UpdateScreen()
                        DisplayError = True
                    End Try
                    If Not DisplayError Then
                        Try
                            Using Trans As Transaction = destDb.TransactionManager.StartTransaction()
                                Try
                                    sourceDb.WblockCloneObjects(blockIds, destDb.BlockTableId, mapping, DuplicateRecordCloning.Replace, False)
                                    Trans.Commit()
                                    Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.AcadDocument.Regen(1)
                                Catch ex As Autodesk.AutoCAD.Runtime.Exception
                                    Trans.Abort()
                                    ed.WriteMessage(vbLf & "Error transferring blocks to current drawing: " & ex.Message & vbLf)
                                    ed.UpdateScreen()
                                    DisplayError = True
                                End Try
                            End Using
                        Catch ex As Autodesk.AutoCAD.Runtime.Exception
                            ed.WriteMessage(vbLf & "Error transferring blocks to current drawing: " & ex.Message & vbLf)
                            ed.UpdateScreen()
                            DisplayError = True
                        End Try
                    End If
                    sourceDb.Dispose()
                Catch ex As Autodesk.AutoCAD.Runtime.Exception
                    ed.WriteMessage(vbLf & "Error reading from source drawing: " & ex.Message & vbLf)
                    ed.UpdateScreen()
                    DisplayError = True
                End Try
            End Using
        Catch ex As Autodesk.AutoCAD.Runtime.Exception
            ed.WriteMessage(vbLf & "Error locking current drawing for update: " & ex.Message & vbLf)
            ed.UpdateScreen()
            DisplayError = True
        End Try

        lblError.Visible = DisplayError

    End Sub

 

Board Manager
StephenPreston
Posts: 400
Registered: ‎05-22-2006
Message 8 of 10 (232 Views)

Re: Add Block When Other Drawings Are Open

11-16-2011 08:04 AM in reply to: soccerazy

BTW (Just checking) Do you actually want to open the document in the editor (i.e. does the user need to see and interact with it). If not, then it is a lot easier (and faster) to open a DWG file in a side database (using Database.ReadDwgFile) to modify it programmatically.

Cheers,

Stephen Preston
Autodesk Developer Network
Valued Mentor
jeff
Posts: 331
Registered: ‎05-12-2009
Message 9 of 10 (220 Views)

Re: Add Block When Other Drawings Are Open

11-16-2011 02:46 PM in reply to: soccerazy

If you do want them to interact with it have you tried making it the active document first then add Block and BlockReference?

You can also find your answers @ TheSwamp
Active Member
soccerazy
Posts: 8
Registered: ‎10-06-2011
Message 10 of 10 (208 Views)

Re: Add Block When Other Drawings Are Open

11-17-2011 01:25 PM in reply to: soccerazy

Thanks for everybody's responses. I do need both the source and destination drawing open for the user to interact with. Using the CommandFlags.Session and locking the drawings is working for my situation (at least so far).

Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.