Accessing Dynamic properties of anonymous block reference

Accessing Dynamic properties of anonymous block reference

Optygon
Explorer Explorer
1,094 Views
6 Replies
Message 1 of 7

Accessing Dynamic properties of anonymous block reference

Optygon
Explorer
Explorer

Hello all,

 

Is there a way to access the dynamic properties of an anonymous block references via c-sharp?
So far I found out that only attributes may be accessed in anonymous block references.

I want to create a configurator, where a single property of all block references (that inherit from a block table record) can be set at once, whilst all other properties remain the same.

So as an example (sorry, I do not have a specific file yet, just basic research up to now):
There are 7 block references of the block definition "Static_Rack" inside my drawing. Every single one of them is anonymous, as I have changed "width" and "length" properties.

When I now execute the configurator, I want to be able to set a third property called "rack_type" for every single appearance inside the drawing, still leaving "width" and "length" of every appearance as they have been.

Can´t really find anything so far.
Thanks in advance.

0 Likes
Accepted solutions (1)
1,095 Views
6 Replies
Replies (6)
Message 2 of 7

ActivistInvestor
Mentor
Mentor

References to anonymous dynamic blocks are no different than references to the 'defining' dynamic block, so the answer is yes, you can get the dynamic block properties for any dynamic block reference.

0 Likes
Message 3 of 7

Optygon
Explorer
Explorer

Okay, So I do have to also use DynamicBlockReferencePropertyCollection I guess? Because last week I tried to access the property collection at a unchanged and a changed block reference while testing some code.

The same code resulted differently:
- Unchanged block reference returned everything as expected
- Changed block reference returned no values at all

Thanks in any case for your quick response, really appreciate it

0 Likes
Message 4 of 7

ActivistInvestor
Mentor
Mentor

I can't comment on the result you observed without seeing some code. References to anonymous dynamic blocks and references to the original user-defined dynamic block definition should be functionally-interchangable.

0 Likes
Message 5 of 7

Optygon
Explorer
Explorer

So, I once again tried using this code.

 

using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using System.Windows.Forms;
using System;

namespace Anonymous_Blocks
{
    public class PropertyDebug
    {
        [CommandMethod("ShowProperties")]
        public void ShowProperties()
        {
            int countAnonymous = 0;
            int countReference = 0;

            Autodesk.AutoCAD.ApplicationServices.Document currentDoc = 
                Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
            Database currentDatabase = currentDoc.Database;

            string message = "Properties of all blocks in the drawing:";

            using(Transaction trans = currentDatabase.TransactionManager.StartTransaction())
            {
                BlockTable blockTable = trans.GetObject(currentDatabase.BlockTableId, OpenMode.ForRead) as BlockTable;
                foreach(ObjectId recordId in blockTable)
                {
                    BlockTableRecord blockTableRecord = trans.GetObject(recordId, OpenMode.ForRead) as BlockTableRecord;

                    // Check if the block table record is dynamic block and NOT null
                    if (blockTableRecord != null && blockTableRecord.IsDynamicBlock)
                    {
                        foreach (ObjectId blockId in blockTableRecord.GetAnonymousBlockIds())
                        {
                            countAnonymous++;
                            message += GetBlockProps(blockId, trans);
                        }
                        foreach (ObjectId referenceId in blockTableRecord.GetBlockReferenceIds(true, true))
                        {
                            countReference++;
                            message += GetBlockProps(referenceId, trans);
                        }
                    }
                    
                }
                trans.Commit();
            }
            MessageBox.Show(string.Format("There are {0} anonymous and {1} reference blocks in the drawing", countAnonymous, countReference));
            MessageBox.Show(message);
        }

        private string GetBlockProps(ObjectId blockId, Transaction transaction)
        {
            string message = "";

            try
            {
                BlockReference blockRef = transaction.GetObject(blockId, OpenMode.ForRead) as BlockReference;
                DynamicBlockReferencePropertyCollection propCollection = blockRef.DynamicBlockReferencePropertyCollection;
                message += "\nBlock: " + blockRef.Name;
                foreach (DynamicBlockReferenceProperty property in propCollection)
                {
                    message += "\n\t" + property.PropertyName + ": " + property.Value;
                }
            }
            catch (System.Exception ex)
            {
                message += "\n" + ex.Message;
            }
            return message;
        }
    }
}

 

I also attached a file with 8 top level block references, 4 of them being clones of the block table record and 4 of them being anonymous due to modified "length" property.

At the GetBlockProps() Method I try to get the blockReference corresponded to the Object ID (line 57).
For all anonymous blocks it results in null.


Unfortunately the official AutoCAD API reference is not very clear to me, raising more questions in general than answering. 

0 Likes
Message 6 of 7

_gile
Consultant
Consultant
Accepted solution

Hi,

The GetAnonymousBlockIds method returns the ObjectIds of the anonymous block defintions (BlockTableRecord), not those of the anonymous inserted block references. This is why line 57 returns null.

Here's a way to get the dynamic properties of all inserted dynamic block references.

[CommandMethod("ShowProperties")]
public void ShowProperties()
{
    var doc = Application.DocumentManager.MdiActiveDocument;
    var db = doc.Database;
    var ed = doc.Editor;
    ed.WriteMessage("\nProperties of all blocks in the drawing:\n");
    using (var tr = db.TransactionManager.StartTransaction())
    {
        var blockTable = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
        foreach (ObjectId btrId in blockTable)
        {
            var btr = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForRead);
            if (!(btr.IsLayout || btr.IsDependent || btr.IsFromExternalReference || btr.IsFromOverlayReference))
            {
                foreach (ObjectId brId in btr.GetBlockReferenceIds(true, false))
                {
                    var br = (BlockReference)tr.GetObject(brId, OpenMode.ForRead);
                    if (br.IsDynamicBlock)
                        ed.WriteMessage(PrintDynamicBlockProperties(br, tr));
                }
            }
        }
        tr.Commit();
    }
}

private static string PrintDynamicBlockProperties(BlockReference br, Transaction tr)
{
    var stringBuilder = new StringBuilder();
    string name = br.Name;
    string effectiveName = 
        ((BlockTableRecord)tr.GetObject(br.DynamicBlockTableRecord, OpenMode.ForRead)).Name;
    if (name == effectiveName)
        stringBuilder.AppendLine($"\n{name}");
    else
        stringBuilder.AppendLine($"\n{name} ({effectiveName})");
    foreach (DynamicBlockReferenceProperty property in br.DynamicBlockReferencePropertyCollection)
    {
        stringBuilder.AppendLine($"\t{property.PropertyName} {property.Value}");
    }
    return stringBuilder.ToString();
}


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 7 of 7

Optygon
Explorer
Explorer

Okay, now I understand the data structure.

 

Thanks for your support! @_gile and @ActivistInvestor 

0 Likes