I am trying to write some code in .net to modify a dimensional constraint that is attached to a source entity of an array that is nested in a block. Specifically I have a line and a dim constraint that control the length of the line. I have tried a couple of methds so far. I can change the dim constraint if I loop through the top level AssocNetwork and SubNetworks looking for the AssocVariable of the constraint then modifying the constraint updates the length of the line. The problem with this approach is that all the BlockReferences get updated to the new line length.
Alternatively, I can access the AssocArray by selecting the block reference. With this method I cannot seem to figure out how to get the AssocVariable from the source entities. Can anyone help with this?
I'm attaching a drawiing and some test code. I'm using Autocad and VS2012.
<CommandMethod("TestEnt")> _
Public Sub TestEnt()
Dim entId As ObjectId
Dim Success As Boolean
Dim doc As Document = Application.DocumentManager.MdiActiveDocument
Dim db As Database = doc.Database
Success = GetTestEntity(entId)
If Success Then
Using trans As Transaction = db.TransactionManager.StartTransaction()
Dim br As BlockReference = DirectCast(trans.GetObject(entId, OpenMode.ForWrite, False), BlockReference)
Dim btr As BlockTableRecord = DirectCast(trans.GetObject(br.BlockTableRecord, OpenMode.ForWrite, False), BlockTableRecord)
For Each NestEntID As ObjectId In btr
Dim ent As Entity = trans.GetObject(NestEntID, OpenMode.ForWrite, False)
If AssocArray.IsAssociativeArray(NestEntID) Then
Dim Ar As AssocArray = AssocArray.GetAssociativeArray(NestEntID)
For Each actionId As ObjectId In Ar.SourceEntities
'doc.Editor.WriteMessage(vbCrLf & "ActionObjId: " & actionId.ToString)
If actionId.ObjectClass.IsDerivedFrom(RXObject.GetClass(GetType(Autodesk.AutoCAD.DatabaseServices.Dimension))) Then
Dim DepIds As ObjectIdCollection = AssocDependency.GetDependenciesOnObject(ent, True, True)
For Each did In DepIds
Dim Dep As AssocDependency = trans.GetObject(did, OpenMode.ForWrite, False)
Dim AnotherActionId As ObjectId = Dep.DependencyBody
If AnotherActionId.ObjectClass.IsDerivedFrom(RXObject.GetClass(GetType(Autodesk.AutoCAD.DatabaseServices.AssocDimDependencyBody))) Then
Dim var As AssocVariable = DirectCast(trans.GetObject(AnotherActionId, OpenMode.ForWrite), AssocVariable)
MsgBox("Variable")
End If
Next
End If
Next
End If
Next
End Using
End If
End Sub
Private Function GetTestEntity(ByRef obj As ObjectId) As Boolean
'get the current active document and database
Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
Dim acCurDB As Database = acDoc.Database
'set the prompt options for the get entity function
Dim prEntOpt As PromptEntityOptions = New PromptEntityOptions(vbLf & "Select an entity: ")
'dont't allow selecting nothing
prEntOpt.AllowNone = False
'set the reject message if not selecting the proper entity
prEntOpt.SetRejectMessage(vbLf & "Must select an entity Douche..... ")
'make it so we can only select a
'prEntOpt.AddAllowedClass(GetType(Entity), True)
'go selct the entity
Dim prEntRes As PromptEntityResult
prEntRes = acDoc.Editor.GetEntity(prEntOpt)
'make sure the user doesn't cancel and
'return the object id for querying
If prEntRes.Status = PromptStatus.OK Then
obj = prEntRes.ObjectId
Return True
Else
Debug.WriteLine(prEntRes.Status)
Return False
End If
End Function
If anyone is interested...Here is some code that works with the TestArray.dwg. I don't know if this is the best approach, but it seems to work.
<CommandMethod("TestEnt")> _
Public Sub TestEnt()
Dim entId As ObjectId
Dim Success As Boolean
Dim doc As Document = Application.DocumentManager.MdiActiveDocument
Dim db As Database = doc.Database
Dim errmsg As String = ""
Dim UnitWidth As String
'select the block
Success = GetTestEntity(entId)
If Success Then
Using trans As Transaction = db.TransactionManager.StartTransaction()
Dim br As BlockReference = DirectCast(trans.GetObject(entId, OpenMode.ForWrite, False), BlockReference)
Dim btr As BlockTableRecord = DirectCast(trans.GetObject(br.BlockTableRecord, OpenMode.ForWrite, False), BlockTableRecord)
If br.IsDynamicBlock Then
Dim dynBRPropCol As DynamicBlockReferencePropertyCollection = br.DynamicBlockReferencePropertyCollection
For Each itm As DynamicBlockReferenceProperty In dynBRPropCol
' doc.Editor.WriteMessage(vbLf & "Proper Name: " & itm.PropertyName & vbLf & _
' "Property Value: " & itm.Value.ToString)
Select Case itm.PropertyName
Case "Width"
UnitWidth = itm.Value.ToString
End Select
Next
For Each NestEntID As ObjectId In btr
Dim ent As Entity = trans.GetObject(NestEntID, OpenMode.ForWrite, False)
If AssocArray.IsAssociativeArray(NestEntID) Then
Dim Ar As AssocArray = AssocArray.GetAssociativeArray(NestEntID)
Dim actionId As ObjectId = Ar.SourceEntities(0)
'doc.Editor.WriteMessage(vbCrLf & "ActionObjId: " & actionId.ToString)
If actionId.ObjectClass.IsDerivedFrom(RXObject.GetClass(GetType(Autodesk.AutoCAD.DatabaseServices.Entity))) Then
Dim RL As Entity = DirectCast(trans.GetObject(actionId, OpenMode.ForWrite), Entity)
'Dim RLbtr As BlockTableRecord = DirectCast(trans.GetObject(RL.BlockId, OpenMode.ForWrite, False), BlockTableRecord)
'Open the AssocNetwork
Dim networkId As ObjectId = AssocNetwork.GetInstanceFromObject(RL.BlockId, False, False, "")
Dim network As AssocNetwork = DirectCast(trans.GetObject(networkId, OpenMode.ForWrite), AssocNetwork)
For Each AnotheractionId As ObjectId In network.GetActions
If AnotheractionId.ObjectClass.IsDerivedFrom(RXObject.GetClass(GetType(Autodesk.AutoCAD.DatabaseServices.AssocVariable))) Then
''Is this action an AssocVariable?*********
Dim var As AssocVariable = DirectCast(trans.GetObject(AnotheractionId, OpenMode.ForWrite), AssocVariable)
'
If Not var Is Nothing Then
Select Case var.Name
Case "RafterLength"
var.SetExpression(UnitWidth, "", True, True, errmsg, True)
End Select
'MsgBox(var.Name)
End If
End If
Next
End If
End If
Next
trans.Commit()
End If
End Using
End If
End Sub