Block definitions, references, attributes, dynamic block properties, exploding
Use this skill when creating block definitions, inserting block references, working with attributes, or reading dynamic block properties.
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(
db.BlockTableId, OpenMode.ForWrite);
// Create a new block definition
BlockTableRecord blockDef = new BlockTableRecord();
blockDef.Name = "MyBlock";
blockDef.Origin = new Point3d(0, 0, 0);
blockDef.Comments = "A custom block";
blockDef.Units = UnitsValue.Millimeters;
blockDef.Explodable = true;
ObjectId blockId = bt.Add(blockDef);
tr.AddNewlyCreatedDBObject(blockDef, true);
// Add entities to the block definition
Line line = new Line(new Point3d(0, 0, 0), new Point3d(10, 10, 0));
blockDef.AppendEntity(line);
tr.AddNewlyCreatedDBObject(line, true);
Circle circle = new Circle(new Point3d(5, 5, 0), Vector3d.ZAxis, 3.0);
blockDef.AppendEntity(circle);
tr.AddNewlyCreatedDBObject(circle, true);
tr.Commit();
}
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(
blockId, OpenMode.ForRead);
foreach (ObjectId entId in btr)
{
Entity ent = (Entity)tr.GetObject(entId, OpenMode.ForRead);
ed.WriteMessage("Entity: {0}\n", ent.GetType().Name);
}
BlockTableRecord space = (BlockTableRecord)tr.GetObject(
db.CurrentSpaceId, OpenMode.ForWrite);
BlockReference blockRef = new BlockReference(
new Point3d(100, 200, 0), // insertion point
blockDefId); // BlockTableRecord ObjectId
blockRef.Rotation = 0.0; // rotation in radians
blockRef.ScaleFactors = new Scale3d(1.0); // uniform scale
blockRef.Normal = Vector3d.ZAxis;
space.AppendEntity(blockRef);
tr.AddNewlyCreatedDBObject(blockRef, true);
AttributeDefinition attDef = new AttributeDefinition(
new Point3d(5, -5, 0), // position
"Default Value", // default value
"TAG_NAME", // tag
"Enter value:", // prompt
textStyleId); // text style
attDef.Height = 2.5;
attDef.Invisible = false;
attDef.Constant = false;
attDef.Verifiable = false;
attDef.Preset = false;
attDef.LockPositionInBlock = false;
// MText attribute definition
attDef.IsMTextAttributeDefinition = true;
MText mtext = new MText();
mtext.Contents = "Multi\\Pline";
attDef.MTextAttributeDefinition = mtext;
attDef.UpdateMTextAttributeDefinition();
blockDef.AppendEntity(attDef);
tr.AddNewlyCreatedDBObject(attDef, true);
// After inserting a BlockReference, add attribute references
BlockTableRecord blockDef = (BlockTableRecord)tr.GetObject(
blockRef.BlockTableRecord, OpenMode.ForRead);
foreach (ObjectId entId in blockDef)
{
AttributeDefinition attDef = tr.GetObject(entId, OpenMode.ForRead)
as AttributeDefinition;
if (attDef == null || attDef.Constant) continue;
AttributeReference attRef = new AttributeReference();
attRef.SetAttributeFromBlock(attDef, blockRef.BlockTransform);
// Position does NOT auto-update from SetAttributeFromBlock — must set manually
attRef.Position = attDef.Position.TransformBy(blockRef.BlockTransform);
attRef.TextString = attDef.TextString; // or set custom value
blockRef.AttributeCollection.AppendAttribute(attRef);
tr.AddNewlyCreatedDBObject(attRef, true);
}
foreach (ObjectId attId in blockRef.AttributeCollection)
{
AttributeReference attRef = (AttributeReference)tr.GetObject(
attId, OpenMode.ForRead);
ed.WriteMessage("Tag: {0}, Value: {1}\n",
attRef.Tag, attRef.TextString);
}
foreach (ObjectId attId in blockRef.AttributeCollection)
{
AttributeReference attRef = (AttributeReference)tr.GetObject(
attId, OpenMode.ForWrite);
if (attRef.Tag == "TITLE")
attRef.TextString = "New Title";
}
if (blockRef.IsDynamicBlock)
{
// Get the original (non-anonymous) block name
BlockTableRecord dynBtr = (BlockTableRecord)tr.GetObject(
blockRef.DynamicBlockTableRecord, OpenMode.ForRead);
string originalName = dynBtr.Name;
// Read and write dynamic properties
DynamicBlockReferencePropertyCollection props =
blockRef.DynamicBlockReferencePropertyCollection;
foreach (DynamicBlockReferenceProperty prop in props)
{
string name = prop.PropertyName;
object val = prop.Value;
bool readOnly = prop.ReadOnly;
bool show = prop.Show;
bool visible = prop.VisibleInCurrentVisibilityState;
short typeCode = prop.PropertyTypeCode;
DynamicBlockReferencePropertyUnitsType units = prop.UnitsType;
string desc = prop.Description;
// Get allowed values (for constrained properties)
object[] allowedValues = prop.GetAllowedValues();
ed.WriteMessage(" {0} = {1} (type: {2})\n", name, val, typeCode);
}
// Set a dynamic property value
foreach (DynamicBlockReferenceProperty prop in props)
{
if (prop.PropertyName == "Distance" && !prop.ReadOnly)
{
prop.Value = 500.0; // set new value
break;
}
}
}
BlockReference.Name returns the anonymous block name for dynamic blocks (e.g., "*U42"); use DynamicBlockTableRecord to get the original nameAppendEntity and AddNewlyCreatedDBObject on the block ref firstSetAttributeFromBlock(attDef, blockRef.BlockTransform) is essential - it positions the attribute correctly based on the block's transform; without it, attributes appear at the wrong locationConstant attributes have fixed values and are NOT included in AttributeCollection on the block referenceBlockTableRecord.ModelSpace and PaperSpace are string constants for the standard space names, not references to the blocks themselvesExplodeToOwnerSpace() adds exploded entities to the parent and erases the block reference; cannot be undone without transaction rollbackConvertToStaticBlock() on a dynamic block reference permanently freezes the current state - the reference can no longer access dynamic propertiesValue is typed as object - cast to the appropriate type (double, string, Point3d, etc.) based on PropertyTypeCodeGetBlockReferenceIds(true, false) returns only direct references; use (false, true) to include nested references and force validity checksacad-layers — block references and entities within blocks inherit layer propertiesacad-editor-input — selecting block references with GetEntity or selection filters (DxfCode.Start "INSERT")acad-mleaders — block references as MLeader block content