.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Locking layer causes strange behaviour

7 REPLIES 7
SOLVED
Reply
Message 1 of 8
Rob.O
854 Views, 7 Replies

Locking layer causes strange behaviour

Hi All,

 

I am wondering if someone can help me figure out what I am doing wrong.  I have code that reads mleader info from a drawing and inputs the data into a table.  Before it does that, the code unlocks the layer that the table is on.  After I am done editing the table, I relock the layer the table is on.  For some reason, when I relock the layer, the boudary lines of the table all shift.  The data stays in the proper location (see attached image).

 

I am still able to edit the table (after unlocking the layer) and if I close the drawing and reopen it, the table goes back to normal.

If I comment out the code that I have to lock the table, the problem does not occur.

 

Here is my code:

 

Dim acLayName As String = "ANO-TABLES"
            Dim acLyrTbl As LayerTable = TryCast(acTrans.GetObject(acCurDb.LayerTableId, OpenMode.ForWrite, False), LayerTable)
            If acLyrTbl Is Nothing Then
                Return
            End If

            Dim acLayTblRec As LayerTableRecord
            For Each objId As ObjectId In acLyrTbl
                acLayTblRec = objId.GetObject(OpenMode.ForRead)
                If acLyrTbl.Has(acLayName) Then
                    acLayTblRec.UpgradeOpen()
                    '' Unlock layer table record
                    If acLayTblRec.IsLocked = True Then
                        acLayTblRec.IsLocked = False
                    End If
                End If
            Next

'' Do stuff to table here

'' Relock layertable record
acLayTblRec.IsLocked = True

 Any ideas???

 

Thanks

7 REPLIES 7
Message 2 of 8
Artvegas
in reply to: Rob.O

I'm not sure about why the table is not updating correctly as it's difficult to replicate from what you have provided, but I had the following comments:

 

1. Are you aware that you can edit a graphical entity using the .NET API, even if it is on a locked layer? I suppose I'm wondering why you are unlocking and locking the layer? If you are editing the table programatically you shouldn't need to do this.

 

2. Have you tried switching back and forth between model and paper space layouts, i.e.:

       acCurDb.TileMode = !acCurDb.TileMode

       acCurDb.TileMode = !acCurDb.TileMode

    Sometimes this helps regen a view.

 

3. I am confused by your sample. You appear to be opening the LayerTable and then iterating each ObjectId as follows:

       - opening each LayerTableRecord for read

       - checking whether the LayerTable has a "ANO-TABLES" layer (which assuming this layer exists, will ALWAYS return true)

       - upgrading each LayerTableRecord for write

       - unlocking each LayerTableRecord

    And then after the loop has finished you appear to lock only the last LayerTableRecord from the loop.

 

Hope this helps.

 

Art.

Message 3 of 8
jeff
in reply to: Artvegas

To add to what Art posted,

 

You can think of

LayerTable("LayerName") for VB or
LayerTable["LayerName"]  for C#

as Indexer Methods which allow access to internal subitems using array-like syntax

 

Passing in the name of the layer will return its ObjectId so something like this

 

  Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor

            Dim layerName As String = "LayerName"

            Using trx As Transaction = db.TransactionManager.StartTransaction()

                Dim bt As BlockTable = trx.GetObject(db.BlockTableId, OpenMode.ForRead)
                Dim currentSpace As BlockTableRecord = trx.GetObject(db.CurrentSpaceId, OpenMode.ForRead)

                Dim layerTbl As LayerTable = trx.GetObject(db.LayerTableId, OpenMode.ForRead)


                If layerTbl.Has(layerName) Then
                    Dim layerTblRecord As LayerTableRecord = trx.GetObject(layerTbl(layerName), OpenMode.ForWrite)
                    layerTblRecord.IsLocked = False
                End If




                trx.Commit()
            End Using

 

 

 Also as Art mentioned one of the overloaded versions of GetObject takes a boolean as a parameter if you want to force objects on Locked layers to be opened.

 

GetObject

 

 

 

 

You can also find your answers @ TheSwamp
Message 4 of 8
Rob.O
in reply to: jeff

Hi guys!

 

Thanks for calling me out on my poor coding abilities! Smiley Happy  I need all the advice I can get as I still have a TON to learn!  Most of the code I write is loosley based on an examples I find in books, online or from the forums.

 

I did not realize that you could force objects on locked layers to be opened, hence the reason I was unlocking the layer first.  I have re-written the code to no longer touch the layers.  Now I simply unlock the table with an overload of GetObjects.

 

After running the code again, I am unfortuantely still seeing the same table behaviour.  A regen does not bring it back and switching tile mode in my code does not bring it back.  The only thing that seems to correct it is closing and reopening the drawing.  Am I doing something wrong in the way I am editing the table?  If the layer is not locked when the code is run, then the problem does not occur.

 

Here is my full code:

<CommandMethod("ECDT_NWDataToTable")> _
    Public Sub ECDT_NWDataToTable()

        '' Declare the current document, database and editor
        Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
        Dim acCurDb As Database = acDoc.Database
        Dim acEd As Editor = DocumentManager.MdiActiveDocument.Editor
       
        '' Start a transaction
        Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()

          Try

                Dim acBt As BlockTable = acDoc.Database.BlockTableId.GetObject(OpenMode.ForRead)
                Dim acBtrMs As BlockTableRecord = DirectCast(acBt(BlockTableRecord.ModelSpace).GetObject(OpenMode.ForRead), BlockTableRecord)

                Dim myLeadVals As New List(Of String)
                Dim myLeadQtys As New List(Of String)                
                Dim Splits As String() = Nothing

                '' Get embed (BOM) multileader contents
                For Each objId As ObjectId In acBtrMs

                    Dim acMlead As MLeader = TryCast(acTrans.GetObject(objId, OpenMode.ForRead), MLeader)
                    If acMlead IsNot Nothing Then
                        Dim MleadStyle As MLeaderStyle = acTrans.GetObject(acMlead.MLeaderStyle, OpenMode.ForRead)
                        Dim strMlStyle As String = MleadStyle.Name
                        If strMlStyle = "ECDT_ANO_NW-BoM" Then
                            Dim strMtextValue As String
                            strMtextValue = acMlead.MText.Text
                            Splits = strMtextValue.Split(New [Char]() {"'"c, "-"c, ChrW(39), ChrW(34), ChrW(13)}, StringSplitOptions.RemoveEmptyEntries)
                            myLeadQtys.Add(Splits(0))
                            myLeadVals.Add(Splits(1))
                            If myLeadQtys.Count > 21 Then
                                MsgBox("Too many BoM tags for data table! Remove tag(s) and try again.", , "Data Error")
                                Exit Sub
                            End If
                        End If
                    End If
                Next
                
		'' Open table and add multileader values to table
                Dim acBtrPs As BlockTableRecord = DirectCast(acBt(BlockTableRecord.PaperSpace).GetObject(OpenMode.ForRead), BlockTableRecord)
                For Each objId As ObjectId In acBtrPs
                    Dim acTable As Table = TryCast(acTrans.GetObject(objId, OpenMode.ForWrite, False, True), Table)
                    If acTable IsNot Nothing Then
                        Dim strTblStylName As String = acTable.TableStyleName
                        If strTblStylName = "ECDT_NW-BillofMaterials" Then
                            
                            Dim range As CellRange = CellRange.Create(acTable, 2, 0, 22, 1)
                            range.DeleteContent()

                            Dim iCnt As Integer = myLeadQtys.Count + 2
                            Dim j As Integer = 0
                            For i As Integer = 2 To iCnt - 1
                                acTable.Cells(i, 0).TextString = myLeadQtys(j)
                                acTable.Cells(i, 1).TextString = myLeadVals(j)
                                j = j + 1
                            Next
                            acTable.DowngradeOpen()
                        End If
                    End If
                Next
                 
                acCurDb.TileMode = Not acCurDb.TileMode
                acCurDb.TileMode = Not acCurDb.TileMode
            Catch ex As Autodesk.AutoCAD.Runtime.Exception
                MsgBox("An error has occured. Please contact you system administrator." & vbCr & vbCr & ex.Message & vbCr & ex.StackTrace)
            Finally
                
            End Try
            acTrans.Commit()
            
        End Using

    End Sub

 

I am also attaching a sample drawing where the issue occurs.

 

Thanks for your help!

 

 

 

 

 

 

Message 5 of 8
Artvegas
in reply to: Rob.O

I ran your code and dwg in AutoCAD 2012 and I see what you mean. When the layer is locked the table cell borders go weird!!

 

I tried a number of different techniques to try to regenerate the table but none seemed to work. I tried to unlock the layer within the command, change the table, and then re-lock the layer. Still to no avail.

 

Welcome to strange happenings in the world of the AutoCAD API Smiley Very Happy

 

Below is my suggested workaround. Although not ideal, it does work!

 

The approach here is to create seperate commands to do the following:
1. Unlock the layer if it is locked.
2. Update the table.
3. Re-lock the layer if it was originally locked.
4. Create a command to send the commands in 1-3 to the command-line.

 

An outline of these commands would be as follows:

 

'***********************************************************************************************************

 

Public Class CommandClass

   
'Class level variable
    Dim isLayerLocked As Boolean = False

    <CommandMethod("UnlockLayer", CommandFlags.NoUndoMarker)>
    Public Sub UnlockLayer()
        'If layer is locked, set isLayerLocked variable to True and unlock the layer.
    End Sub

    <CommandMethod("UpdateTable", CommandFlags.NoUndoMarker)>
   Public Sub UpdateTable ()
       ‘Update table.
    End Sub

    <CommandMethod("ReLockLayer", CommandFlags.NoUndoMarker)>
    Public Sub ReLockLayer ()
        ‘Check isLayerLocked variable, and if True then re-lock the layer.
    End Sub

    <CommandMethod("ECDT_NWDataToTable")>
    Public Sub ECDT_NWDataToTable()
        Dim doc As Document = Application.DocumentManager.MdiActiveDocument
        ‘Send commands to command-line.
        doc.SendStringToExecute("UnlockLayer UpdateTable LockLayer ", False, False, False)
    End Sub

End Class

 

'***********************************************************************************************************

 

Notes:
1. The UnlockLayer, UpdateTable and ReLockLayer commands have the CommandFlags.NoUndoMarker in command attribute.
    I've done this so that if the user wants to UNDO the ECDT_NWDataToTable command, they won't have to perform repeated
    undos for each of the sub-commands.

2. The echoCommand parameter in the SendStringToExecute() method is set to False, so that the user will only see
    ECDT_NWDataToTable in the command-line.

 

 

Hope this helps.

 

Art

Message 6 of 8
Rob.O
in reply to: Artvegas

Hey Art!  This is great stuff!  Works great! Smiley Happy

 

Too bad about the table not updating properly.  Seems to be a bug of sorts?  Do you know if there is a procedure that differs from the regular method for AutoCAD bug reporting (Product Feedback Form) to get this info to Autodesk so they can look into it?

 

Thanks for all of your help!  I will accept your post as the solution, but if you (or anyone else) discover how to get the table to update properly, please let me know!

 

Thanks again!

 

 

Message 7 of 8
Artvegas
in reply to: Rob.O

Hi,

 

I had another look and this issue also seems to be related to how your table and its table style is formatted.

 

Please refer to the attached ModifiedTest.dwg (AutoCAD 2010 dwg format).

 

I added a new ECDT_NW-BillofMaterials table to the locked layer using the TABLE command. I left the 'Insert Table' dialog defaults and hit OK.. Refer to the attached InsertTableDialog.jpg image which shows the default settings I used.

 

Now when I update the tables (with the layer locked), the one I inserted from scratch works fine but the one you had loses its borders. Refer to the attached Screenshot.jpg image which shows the results.

 

Might be worth spending some time looking into your table and the table style you're using.

 

Cheers,
Art

 

p.s. I believe the only way you could get this directly addressed by Autodesk is by subscribing to the Autodesk Developer Network, of which I am not a member: http://autodesk.com/developer

Message 8 of 8
Rob.O
in reply to: Artvegas

Thanks Art!

 

I will definately look into this!

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost