Accessing Dynamic block properties requires that the BlockReference that owns the properties be open in a transaction.
The problem is that when you access the dynamic block insertion via the DBObject property of the ObjectEventArgs from the handler of an event that passes that type (like ObjectModified), you cannot assume the notifying DBObject is open in a transaction.
--
http://www.caddzone.com
AcadXTabs: MDI Document Tabs for AutoCAD 2008
Supporting AutoCAD 2000 through 2008
http://www.acadxtabs.com
wrote in message news:5864334@discussion.autodesk.com...
This is my standard block (dynamic) insert from file technique...
Private box1 As Point3d
Private box2 As Point3d
Private brPanel As BlockReference
Private btrPanel As BlockTableRecord
Public Sub InsertNewPanel()
Dim dblInsert As Point3d
Dim dblP2 As Point3d
Dim objResult As PromptPointResult
Dim bt As BlockTable
Dim btr As BlockTableRecord = Nothing
Dim btrMSpace As BlockTableRecord
Dim id As ObjectId
Dim db As Autodesk.AutoCAD.DatabaseServices.Database = HostApplicationServices.WorkingDatabase
Using trans As Transaction = db.TransactionManager.StartTransaction
Dim ed As Autodesk.AutoCAD.EditorInput.Editor = Application.DocumentManager.MdiActiveDocument.Editor
'insert block and rename it
Try
'pick single insert point method
'add support for pick box method
Dim op As PromptPointOptions = New PromptPointOptions("Pick the location for the new shear wall panel")
op.AllowArbitraryInput = False
op.AllowNone = False
objResult = ed.GetPoint(op)
If objResult.Status = PromptStatus.Error Then MsgBox("Pick error" & objResult.Status.ToString)
If objResult.Status = PromptStatus.OK Then
dblInsert = objResult.Value
'insert by box section
If Building.InsertByBox = True Then
Dim pco As New PromptCornerOptions("Pick second point for Panel: ", dblInsert)
pco.AllowArbitraryInput = False
pco.AllowNone = False
pco.UseDashedLine = True
Dim ppr As PromptPointResult = ed.GetCorner(pco)
If ppr.Status = PromptStatus.OK Then
dblP2 = ppr.Value
End If
End If
'add getCorner and insert block to fit in box
bt = trans.GetObject(db.BlockTableId, OpenMode.ForWrite)
If bt.Has(srwlBuilding.strSourcePanelBlockName) Then
'block found, get instance for copying
btrPanel = trans.GetObject(bt.Item(srwlBuilding.strSourcePanelBlockName), OpenMode.ForRead)
Else
'block not found, insert into drawing
Using sourcedb As Database = New Database(False, False)
Try
sourcedb.ReadDwgFile(srwlBuilding.strSourcePanelBlockPath, IO.FileShare.Read, True, "")
id = db.Insert(srwlBuilding.strSourcePanelBlockPath, sourcedb, True)
btrPanel = trans.GetObject(id, OpenMode.ForWrite)
btrPanel.Name = "Panel-" & Name & "-" & PanelID.ToString
Catch ex As System.Exception
Dim aex As New System.Exception("Block file not found" & srwlBuilding.strSourcePanelBlockPath & "-", ex)
Throw aex
Exit Sub
End Try
sourcedb.Dispose()
End Using
End If
btrMSpace = trans.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
brPanel = New BlockReference(dblInsert, btrPanel.ObjectId)
btrMSpace.AppendEntity(brPanel)
trans.AddNewlyCreatedDBObject(brPanel, True)
Me.BlockRefHandle = brPanel.Handle
Me.BlockHandle = btrPanel.Handle
End If
trans.Commit()
Catch ex As System.Exception
Dim aex2 As New System.Exception("Error in inserting new Panel block. ", ex)
Throw aex2
Finally
ed.WriteMessage(vbLf & "Command: ")
If Not trans Is Nothing Then trans.Dispose()
End Try
If Building.InsertByBox = True Then
Try
SetShape(dblInsert, dblP2)
Catch ex As System.Exception
Dim aex3 As New System.Exception("Error while setting Panel shape: ", ex)
Throw aex3
End Try
End If
SetDefaults()
End Using
End Sub
this chunk is responsible for putting the dynamic block into the drawing into modelspace.
This next chunk is my event handler that listens to AutoCAD. It is fired off 3 time when modifying a (dynamic only) property using AutoCAD's built in properties palette. If the object is 'found' to be one of the objects I am tracking in my object tree, then I react by re-reading the objects properties. When the code reads the dynamic properties, third time (event triggered) crashes, because no dynamic properties can be found (kind of...)
Private Sub callback_ObjectModified(ByVal sender As Object, ByVal e As ObjectEventArgs)
If IgnoreEvents Then Exit Sub
Dim ibe As Boolean = Me.IgnoreEvents
Try
IgnoreEvents = True
If Not e.DBObject.IsWriteEnabled Then
IgnoreEvents = ibe
WorkEvent(e.DBObject, "Modified")
End If
Catch ex As System.Exception
Dim aex As New System.Exception("Error at Modify Object AutoCAD Event: ", ex)
Me.HandleError(aex)
Finally
IgnoreEvents = ibe
End Try
End Sub
Public Sub WorkEvent(ByRef dbObject As DBObject, ByVal strTask As String)
Try
Select Case dbObject.GetType.ToString
Case "Autodesk.AutoCAD.DatabaseServices.BlockReference"
'If e.DBObject.IsModified = False Then
'Debug.Print("BlockReference " & strTask)
Try
Dim objCheck As Object = Me.Levels.ContainsHandle(dbObject.Handle)
If objCheck(0) Then
'Debug.Print(objCheck(1).ToString & objCheck(2).ToString)
Select Case strTask
Case "Added"
Case "Modified"
Me.ReactToChange(objCheck)
Case "Erased"
Me.ReactToErased(objCheck)
Case "UnErased"
Me.ReactToUnErase(objCheck)
End Select
End If
Catch ex As System.Exception
Dim aex As New System.Exception("Error working BlockReference event: ", ex)
Throw aex
End Try
'End If
Case "Autodesk.AutoCAD.DatabaseServices.Polyline"
'Debug.Print("Polyline " & strTask)
Try
Dim objCheck As Object = Me.Levels.ContainsHandle(dbObject.Handle)
If objCheck(0) Then
'Debug.Print(objCheck(1).ToString & objCheck(2).ToString)
Select Case strTask
Case "Added"
Case "Modified"
Me.ReactToChange(objCheck)
Case "Erased"
Me.ReactToErased(objCheck)
Case "UnErased"
Me.ReactToUnErase(objCheck)
End Select
End If
Catch ex As System.Exception
Dim aex As New System.Exception("Error working Polyline event: ", ex)
Throw aex
End Try
End Select
Catch ex As System.Exception
Dim aex As New System.Exception("Error Working Event: ", ex)
Throw aex
End Try
End Sub
This is the snippet that accesses the dynamic property as a separate process from a custom built palette.
Public Overridable Function GetDynProperty(ByVal bref As BlockReference, ByVal PropertyName As String) As Object
Dim db As Autodesk.AutoCAD.DatabaseServices.Database = HostApplicationServices.WorkingDatabase
Dim ThisDrawing As Autodesk.AutoCAD.ApplicationServices.Document = Application.DocumentManager.MdiActiveDocument
Dim objProp As Object = Nothing
Using trans As Transaction = db.TransactionManager.StartTransaction
Dim dlock As DocumentLock = Nothing
Try
Try
dlock = ThisDrawing.LockDocument
Catch ex As Exception
Dim aex As New System.Exception("Error locking document for to get Dynamic Property: ", ex)
Throw aex
End Try
Dim brObj As BlockReference = trans.GetObject(bref.Id, OpenMode.ForRead)
If Not brObj Is Nothing Then
Dim dpcPanel As DynamicBlockReferencePropertyCollection
Dim dpPanel As DynamicBlockReferenceProperty
If brObj.IsDynamicBlock = True Then
Try
dpcPanel = brObj.DynamicBlockReferencePropertyCollection
For Each dpPanel In dpcPanel
Select Case dpPanel.PropertyName.ToUpper
Case PropertyName
objProp = dpPanel.Value 'this is the point of crash
Exit For
End Select
Next
Catch ex As System.Exception
Dim aex As New System.Exception("Error getting dynamic property for " & PropertyName, ex)
Throw aex
End Try
End If
End If
'trans.Commit()
Catch ex As System.Exception
Dim aex As New System.Exception("Error getting dynamic property for " & PropertyName, ex)
Throw aex
Finally
If Not trans Is Nothing Then trans.Dispose()
If Not dlock Is Nothing Then dlock.Dispose()
End Try
End Using
Return objProp
End Function