Author Topic: Update attribute based on event  (Read 2337 times)

0 Members and 1 Guest are viewing this topic.

Daverode

  • Guest
Update attribute based on event
« on: May 06, 2011, 12:01:25 PM »
Can anyone help me with this problem? :x
Code: [Select]

   Private Sub callback_commandWillStart(ByVal sender As Object, ByVal e As CommandEventArgs)
        If e.GlobalCommandName = "EATTEDIT" Then
            MsgBox("hey")
            Return
        ElseIf e.GlobalCommandName = "POWEREDITINAPP" Then
            AddHandler myDB.ObjectModified, AddressOf callback_ObjectModified
            AddHandler myDoc.CommandEnded, AddressOf callback_CommandEnded
        End If
    End Sub
    Private Sub callback_ObjectModified(ByVal sender As Object, ByVal e As ObjectEventArgs)
        Dim trans As Transaction = e.DBObject.Database.TransactionManager.StartTransaction
        Try
            Dim obj As Object = trans.GetObject(e.DBObject.Id, OpenMode.ForRead)
            If obj.GetType.Name.ToString = "BlockReference" Then
                If Not IDList.Contains(e.DBObject.Id) Then
                    IDList.Add(e.DBObject.Id)
                    Debug.Print(e.DBObject.Id.ToString)
                    Debug.Print(sender.ToString)
                    MsgBox(obj.GetType.Name.ToString)
                    Dim myBlockRef As BlockReference = e.DBObject.Id.GetObject(OpenMode.ForRead)
                    MsgBox(myBlockRef.ObjectId.ToString)
                    Dim BTR As BlockTableRecord = myBlockRef.BlockTableRecord.GetObject(OpenMode.ForRead)
                    MsgBox(BTR.Name)
                End If
            End If
        Catch ex As Exception
        End Try
        trans.Dispose()
    End Sub
    Private Sub callback_CommandEnded(ByVal sender As Object, ByVal e As CommandEventArgs)
        Dim myDwg As Document = DocumentManager.MdiActiveDocument
        Dim myDB As Database = ApplicationServices.Application.DocumentManager.MdiActiveDocument.Database
        Try
            For Each objid In IDList
                Using myTrans As Transaction = myDwg.TransactionManager.StartTransaction
                    Dim myTags As New ArrayList
                    Dim myStrings As New ArrayList
                    myTags.Add("FunctionText")
                    myStrings.Add("This is a test")
                    'SetAttributes(objid, myTags, myStrings)
                    myTrans.Commit()
                End Using
            Next
            IDList.Clear()
            Catch ex As Exception
        End Try
        RemoveHandler myDB.ObjectModified, AddressOf callback_ObjectModified
        RemoveHandler myDoc.CommandEnded, AddressOf callback_CommandEnded
    End Sub


    Public Sub SetAttributes(ByVal BlockID As ObjectId, ByVal TagList As ArrayList, ByVal StringList As ArrayList)
        Dim myTransMan As DatabaseServices.TransactionManager
        Dim myTrans As DatabaseServices.Transaction
        Dim myDwg As Document

        myDwg = Application.DocumentManager.MdiActiveDocument
        myTransMan = myDwg.TransactionManager
        myTrans = myTransMan.StartTransaction

        Dim myBlockRef As BlockReference
        Dim myAttColl As AttributeCollection
        myBlockRef = BlockID.GetObject(OpenMode.ForWrite, False)
        myAttColl = myBlockRef.AttributeCollection
        Dim myEnt As ObjectId
        Dim myAttRef As AttributeReference
        For Each myEnt In myAttColl
            myAttRef = myEnt.GetObject(OpenMode.ForWrite, False)
            If TagList.Contains(myAttRef.Tag) Then
                Dim X As Integer = TagList.BinarySearch(myAttRef.Tag)
                If X >= 0 Then
                    myAttRef.TextString = StringList(X)
                End If
            End If
        Next
        myTrans.Commit()
        myTrans.Dispose()
        myTransMan.Dispose()
    End Sub

I'm trying to write code in vb.net to update an attribute in a block based on the change of another attribute in the same block.
I'm fairly new to vb.net and programming in general. Included is a sample of code I've written and it seems to work until I try to open the Attribute reference for write. Is this because the block is already open for write?

Does anyone have any ideas on how I might accomplish this task a different way?

Thanks
Dave

Jeff H

  • Needs a day job
  • Posts: 6151
Re: Update attribute based on event
« Reply #1 on: May 06, 2011, 08:31:30 PM »
Welcome to Swamp, and a veteran should give you a welcome for it to actually count.

Here is a idea and if I am incorrect about Kean's intentions I am sure someone will catch it.

Using Kean's idea from here

You would have 2 collections
1. ObjectIds of the BlockTableRecords that your BlockReference's reference that you want the update.
2. ObjectIds of the BlockReferences modified that the BlockTableRecord ObjectId is contained in the first collection.

If first collection == BlockIds and second collection == UpdateReferenceIds

In your callback_ObjectModified
you check if ObjectModified is a Blockreference and if it's BlockTableRecord property(which is the ObjectId of the BlockTableRecord referenced by the block reference)
is contained in BlockIds collection you add the Blockrefence's ObjectID to UpdateReferenceIds collection.

In your callback_CommandEnded
'For each ObjectId' in UpdateReferenceIds you do your checking to see if attribute change and if so update attributes.
Then you clear or make empty the UpdateReferenceIds collection.


Things to note
Dynamic Blocks
Wait to see what these smarter guys here suggest

If you need more help please reply back.
 


Jeff H

  • Needs a day job
  • Posts: 6151
Re: Update attribute based on event
« Reply #2 on: May 07, 2011, 01:43:01 AM »
Download BlockWatch.zip posted in #4 reply by Fixo posted  here http://forums.augi.com/showthread.php?t=129638

kaefer

  • Guest
Re: Update attribute based on event
« Reply #3 on: May 07, 2011, 06:30:05 PM »
Can anyone help me with this problem? :x

I'd wager a guess that the nested transaction inside an event handler spoils it for you.

Don't know about POWEREDITINAPP, but hey, DDATTE modifies the block reference while EATTEDIT does not.

Other aspects for consideration (no offence meant, even as I don't speak VB):
Transactions shouldn't be started in loops.
The type test should be TryCast As or TypeOf Is, not a string comparison with a type name.
The local data containers should be typed, either List<ObjectId>, List<string> etc. or AutoCAD's ObjectIdCollection and so on.
BinarySearch works only on a sorted collection (not known if that's the case), IndexOf is more like it. No need for Contains.
Problem illustrations should be minimal but complete code samples.

Cheers