Dynamic Block's visibility isn't modified

Dynamic Block's visibility isn't modified

Anonymous
Not applicable
3,049 Views
10 Replies
Message 1 of 11

Dynamic Block's visibility isn't modified

Anonymous
Not applicable

Hello,

 

I'm trying to modify my dynamic block's visibility. My code successfully displays the correct visibility of the block but it seems as if it doesn't commit to it. What I mean by this is, when I close the drawing and open it back up, it is back to its default state (or first visible state). Below are screenshots of the results I get (along with the code below those screenshots). The first image shows an example of the default state when I manually insert it without trying to modify the visibility.

 

Default state ("Panneau 48x38x12_AC_AF"):

dynamicblock_DefaultState.png

 

Take a look at the code when I step through it.

dynamicblock_Visibility.png

 

My prop.Value is equal to the default state even once I've stepped through when my variable panelVal is as another state ... What's weird is; it displays the correct visibility of the panelVal, but has the selection still set to the default state:

dynamicblock_NewState.png

 

If I then close the drawing and open it back up, it is set back to the default state... If I manually change it, there's no problem. It keeps the changes, but the point of this is to get it all automated.

 

Code

 

    Private Sub ModifyVisibility(ByVal Path As String, ByVal blkname As String)
        Dim bId As ObjectId
        Dim utils As New AcadNetUtils
        Dim currLayer As New clsLayer
        Dim acDoc As Document = AcApp.Application.DocumentManager.MdiActiveDocument
        Dim acCurDb As Database = acDoc.Database
        Dim tempDb As New Database(False, True)
        Dim ed As Editor = acDoc.Editor
        Dim acBlkTbl As BlockTable
        Dim acBlkTblRec As BlockTableRecord
        Dim br As BlockReference
        Dim insertJig As InsertBlockJig
        Dim pr As PromptResult
        Dim oldSnapMode As Integer = AcApp.Application.GetSystemVariable("SNAPMODE")

        Using lock As DocumentLock = acDoc.LockDocument
            Autodesk.AutoCAD.Internal.Utils.SetFocusToDwgView()
            AcApp.Application.SetSystemVariable("SNAPMODE", 1)
            'Get the current database and start the Transaction Manager
            tempDb.ReadDwgFile(Path, FileOpenMode.OpenForReadAndReadShare, True, "")
            acCurDb.Insert(blkname, tempDb, False)
            tempDb.Dispose()

            'Start a transaction
            Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()
                'Open Model space for write
                acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead)
                acBlkTblRec = acTrans.GetObject(acBlkTbl(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
                br = New BlockReference(Point3d.Origin, acBlkTbl.Item(blkname))
                Dim btr As BlockTableRecord = acTrans.GetObject(br.DynamicBlockTableRecord, OpenMode.ForRead)

                'Sets the correct text for the panel. ex: "Panneau 60x49x18_AC"
                If br <> Nothing AndAlso br.IsDynamicBlock Then
                    Dim pc As DynamicBlockReferencePropertyCollection = br.DynamicBlockReferencePropertyCollection
                    Dim panelVal As String = "Panneau 60x49x18_AC"

                    'Loop through to get the info for each property
                    For Each prop As DynamicBlockReferenceProperty In pc
                        Select Case prop.PropertyName
                            Case "Visibility"
                                prop.Value = panelVal 'DOES NOT GET MODIFIED
                        End Select
                    Next
                End If

                'Using InsertBlockJig class to insert the block
                insertJig = New InsertBlockJig(br)
                pr = ed.Drag(insertJig)
                If pr.Status = PromptStatus.OK Then
                    bId = acBlkTblRec.AppendEntity(br) 'Add the object to the drawing
                    acTrans.AddNewlyCreatedDBObject(br, True) 'Tell the transaction
                    acTrans.Commit() 'Commit the changes and dispose of the transaction

                    'Release objects
                    acBlkTblRec = Nothing
                    acBlkTbl = Nothing
                End If
            End Using
        End Using
    End Sub

What could be causing this issue? Am I not setting the block's visibility correctly?

 

Thanks for the help in advance,

Alex

 

0 Likes
Accepted solutions (1)
3,050 Views
10 Replies
Replies (10)
Message 2 of 11

Anonymous
Not applicable

TL;DR version

 

I am inserting a dynamic block which displays a panel with different visibilities. 

 

The property name is "Visibility" and the value is chosen based on certain choices the user makes in the program. For example purposes, I used the visibilities: "Panneau 48x38x12_AC_AF" and "Panneau 60x49x18_AC".  These are two visibility states that the dynamic block can take.

 

Upon insertion with visibility "Panneau 60x49x18_AC", it displays the correct visibility/panel but still has the "Panneau 48x38x12_AC_AF" selected in the list.  So when I reopen my drawing, it is suddenly displayed as "Panneau 48x38x12_AC_AF".

 

I doubt this is normal behaviour. I do not have this problem when manually changing the visibility state.

 

 

 

 

0 Likes
Message 3 of 11

SENL1362
Advisor
Advisor

Alex,

Have you looked at and or tested on a simple sample like this from my other mentor Philippe Leefsma:

http://adndevblog.typepad.com/autocad/2012/08/how-to-access-and-modify-a-dynamicblockreference-prope...

 

 

Pay attension to the test for the ReadOnly property "!prop.ReadOnly":

 

Alex, have you looked at it on a simple sample like this:

foreach (DynamicBlockReferenceProperty prop in props)
            {
                object[] values = prop.GetAllowedValues();
                if (prop.PropertyName == "Visibility" && !prop.ReadOnly)
                {
                    if (prop.Value.ToString() == values[0].ToString())
                        prop.Value = values[1];
                    else
                        prop.Value = values[0];
                }

 

0 Likes
Message 4 of 11

Anonymous
Not applicable

Hi SENL,

 

Yep I've tried that but no change, still the same issue. The property is not read only.

 

I have no idea what I'm doing wrong...

 

Alex

0 Likes
Message 5 of 11

SENL1362
Advisor
Advisor

Alex, i have little to no knowledge of VB.NET, thus wrote this C# version to test the behavior.

Maybe you can read it as a sample and use it to test you're VB version in the different stages.

 

Notes:

1. In C# we have to Add Attributes(or Dynamic Properties) to the BlockReference our self, it's not automatically added when creating the BlockReference.

2. Then the Dynamic Properties are handled slightly different from normal Attributes.

3. Also be careful with allowed values, that's why i added the dictionary of Case Insensitive  keys

 

Tips to find the problem:

- does you're code reach the assignment of the property?

- Is it the correct Value?

- try the code without the jig and insert block.

 

Good luck.

 

 

 

 

 [CommandMethod("VDBA")]
        public static void VisibilityDynamicBlockAttribute()
        {
            Document doc = null;
            Database db = null;
            Editor ed = null;

            string blkName = "Block1";
            string visPropName = "VISIBILITY";
            string visPropValue = "VisVal1";

            try
            {
                doc = AcadApp.DocumentManager.MdiActiveDocument;
                if (doc == null)
                    throw new System.Exception("No MdiActiveDocument");
                db = doc.Database;
                ed = doc.Editor;


                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                    if (!bt.Has(blkName))
                        throw new System.Exception("Block not found: " + blkName);
                    var blkId = bt[blkName];

                    var ms = (BlockTableRecord)tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite);

                    var insPnt = new Point3d(10, 20, 0);
                    var blkRef = new BlockReference(insPnt, blkId);
                    ms.AppendEntity(blkRef);
                    tr.AddNewlyCreatedDBObject(blkRef, true);

                    //Add Attributes to BlockReference, this is a separate action in C#

                    BlockTableRecord blk = (BlockTableRecord)tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead);
                    // if (blkRef.IsDynamicBlock)
                    //     blk = (BlockTableRecord)tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead);
                    //else
                    //     blk = (BlockTableRecord)tr.GetObject(blkRef.DynamicBlockTableRecord, OpenMode.ForRead);

                    foreach (ObjectId id in blk)
                    {
                        DBObject dbObj = (DBObject)tr.GetObject(id, OpenMode.ForRead);
                        AttributeDefinition attDef = dbObj as AttributeDefinition;
                        if ((attDef != null) && (!attDef.Constant))
                        {
                            using (AttributeReference attRef = new AttributeReference())
                            {
                                attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform);
                                attRef.TextString = "";
                                blkRef.AttributeCollection.AppendAttribute(attRef);
                                tr.AddNewlyCreatedDBObject(attRef, true);
                            }
                        }
                    }
                    if (blkRef.IsDynamicBlock)
                    {
                        var dynProps = blkRef.DynamicBlockReferencePropertyCollection;
                        foreach (DynamicBlockReferenceProperty dynProp in dynProps)
                        {
                            if (!dynProp.ReadOnly && Regex.IsMatch(dynProp.PropertyName, visPropName, RegexOptions.IgnoreCase))
                            {
                                var allVals=dynProp.GetAllowedValues();
                                var dynVals=new Dictionary<string,string>(StringComparer.OrdinalIgnoreCase);
                                allVals.Cast<string>().ToList().ForEach(n=> dynVals[n]=n);

                                if (!dynVals.ContainsKey(visPropValue))
                                    ed.WriteMessage("\n Warning: {0} Key not found: {1}. Apply Default.", visPropName, visPropValue);
                                else
                                    dynProp.Value = dynVals[visPropValue];
                            }
                        }
                    }
                    tr.Commit();
                }

            }
            catch (System.Exception ex)
            {
                if (ed != null)
                    ed.WriteMessage("\n Error in VisibilityDynamicBlockAttribute: {0}", ex.Message);
            }
        }

 

 

 

 

0 Likes
Message 6 of 11

Anonymous
Not applicable
I'll study your example and give feedback, thanks!
0 Likes
Message 7 of 11

Anonymous
Not applicable

I have a question for your example. I see you select "VisVal1" for the visibility of your dynamic block when it is usually "VisValAll" as default, right?

 

When the block is inserted, I suppose you can see the "VisVal1", but when you click on the arrow for the different visibilities (from your attached screenshot) does it still display "VisValAll" even though you chose "VisVal1"?

 

Secondly, if you save, close and reopen the drawing, does it still display "VisVal1" or did it go back to "VisValAll"?

 

Because this is the problem I have currently, it displays the correct one but when I restart AutoCAD, it went back to the default value ... And it goes through the code without any problems. That's what is really freaking me out haha I have no idea why it's doing that.

0 Likes
Message 8 of 11

SENL1362
Advisor
Advisor
Accepted solution

 

Screenshot_1.png

Absolutely right, see attachment, AutoCAD 2016 sample of dynamic block.

 

 

Screenshot_2.png

No, when inserted by the function VDBA, the current(or selected) value is VisVal1.

 

 

Screenshot_4.png

Yes the current(or selected) value is still VisVal1.

 

 

 

Screenshot_5.png

Take it easy because it is only week 2 of this year.....

Could you try the C# example and the attached drawing to verify that there is nothing wrong with youre installation?

 

 

 

 

 

 

 

Message 9 of 11

Anonymous
Not applicable

Ahhhh your dynamic block helped a lot. I sent it over to the engineers and they were able to see that you have a block with two other nested blocks. I think that's what I was missing.

 

Your last answer was excellent and helped me find the solution. Thank you!!

0 Likes
Message 10 of 11

SENL1362
Advisor
Advisor

Alex,

some extra information is needed here i think.

 

 

The dynamic block(Block1) does not have nested blocks, only nested entities, a circle and a rectangle.

Then a Visiblity Parameter is added with three states:

VisValALL: Show Circle and Rectangle

VisVal1: Show Rectangle

VisVal2: Show Circle.

 

Then one instance/BlockReference is added to ModelSpace, but that one doesn't influence the behaviour of the other BlockReferences.

It prevent only prevent Purge that Dynamic Block.

 

Keep in mind that what happens when you insert a dynamic block is that a copy of the Block Definition is made, named *Uxxx.

Both Block1 and *Uxxx belongs to the dynamic Block.

 

Thus you have:

1. a drawing (dynBlock1.dwg),

2. a ModelSpace wit one BlockReference to a dynamic block *Uxxx (and indirect to Block1)

3. a BlockDefinition(Block1)  containing a Circle and Rectangle and a VisibilityParameter.

4. a BlockTable containing Modelspace, Paperspace, Block1, *Uxxx.

 

 

You can find both Block Definitions via the BlockRefence:

originalBlk = (BlockTableRecord)tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead);
anonymousBlk = (BlockTableRecord)tr.GetObject(blkRef.DynamicBlockTableRecord, OpenMode.ForRead);

 

P.s. You should never use a Drawing containing a BlockDefinition named equally as the Drawing, thus renaming the drawing to Block1.dwg is not a good idea.

 

 

 

Message 11 of 11

Anonymous
Not applicable
Ahh I see! Thanks for clearing that up. I'm pretty new to AutoCAD still hehe.
0 Likes