Dynamic Block Becomes Static After Insertion

Dynamic Block Becomes Static After Insertion

ilovejingle
Enthusiast Enthusiast
623 Views
5 Replies
Message 1 of 6

Dynamic Block Becomes Static After Insertion

ilovejingle
Enthusiast
Enthusiast

I am trying to write a program to replace the old block with the new block. both blocks are dynamic. It seems the new blockreference becomes static after insertion

 

Is there any simpler way to insert a dynamic block which already exists in the drawing?

 

Here is my code : 

 

        [CommandMethod("RP")]
        public void cmdRP()
        {
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
            var optEnt1 = new PromptEntityOptions("Please Select Entity to be replaced : ");
            var optEnt2 = new PromptEntityOptions("Please Select Enttity to Replace the orginal Entity : ");

            optEnt1.SetRejectMessage("Only Support Block Reference ");
            optEnt2.SetRejectMessage("Only Support Block Reference ");

            optEnt1.AddAllowedClass(typeof(BlockReference), true);
            optEnt2.AddAllowedClass(typeof(BlockReference), true);

            var blkOld = ed.GetEntity(optEnt1);
            if (blkOld.Status != PromptStatus.OK) return;
            var blkNew = ed.GetEntity(optEnt2);
            if (blkNew.Status != PromptStatus.OK) return;

            using (Transaction trans = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
            {
                try
                {
                    var blkRefOld = trans.GetObject(blkOld.ObjectId, OpenMode.ForRead) as BlockReference;
                    var blkRefNew = trans.GetObject(blkNew.ObjectId, OpenMode.ForRead) as BlockReference;

                    var blkMat = blkRefOld.BlockTransform;
                    var newBlkRef = new BlockReference(new Point3d(0, 0, 0), blkRefNew.BlockTableRecord);

                    newBlkRef.SetDatabaseDefaults();
                    newBlkRef.TransformBy(blkMat);

                    var bt = trans.GetObject(HostApplicationServices.WorkingDatabase.BlockTableId, OpenMode.ForRead) as BlockTable;
                    var ms = trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;

                    ms.AppendEntity(newBlkRef);
                    

                    trans.AddNewlyCreatedDBObject(newBlkRef, true);

                    RXClass rxclass = RXObject.GetClass(typeof(AttributeDefinition));
                    var btr = trans.GetObject(blkRefOld.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;
                    var collection = newBlkRef.AttributeCollection;

                    if (btr.HasAttributeDefinitions)
                    {
                        foreach (ObjectId objId in btr)
                        {
                            if (objId.ObjectClass.IsDerivedFrom(rxclass))
                            {
                                var attDef = trans.GetObject(objId, OpenMode.ForRead) as AttributeDefinition;
                                if (!attDef.Constant)
                                {
                                    var attRef = new AttributeReference();
                                    attRef.SetAttributeFromBlock(attDef,blkMat);
                                    collection.AppendAttribute(attRef);
                                    trans.AddNewlyCreatedDBObject(attRef, true);
                                }
                            }
                        }
                    }

                    bgFunction.SyncDynamicBlockProps(blkRefOld.ObjectId, newBlkRef.ObjectId, trans);
                    blkRefOld.UpgradeOpen();
                    blkRefOld.Erase();

                }
                catch (Autodesk.AutoCAD.Runtime.Exception ex)
                {
                    ed.WriteMessage("Error : MAIN Method.");
                }
                finally
                {
                    trans.Commit();
                }
            }
        }
0 Likes
624 Views
5 Replies
Replies (5)
Message 2 of 6

_gile
Consultant
Consultant

Hi,

 

What about this method?

bgFunction.SyncDynamicBlockProps

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 3 of 6

ilovejingle
Enthusiast
Enthusiast

This method has no relevance to this topic, it just try to copy all attributes value from the old block to the new block. I should remove it from my code before posting, sorry for that.

0 Likes
Message 4 of 6

_gile
Consultant
Consultant

May be you can start from this (not deeply tested)

        [CommandMethod("RP")]
        public static void CmdRp()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            var opts = new PromptEntityOptions("\nPlease Select Entity to be replaced : ");
            opts.SetRejectMessage("Only Support Block Reference ");
            opts.AddAllowedClass(typeof(BlockReference), true);

            var result = ed.GetEntity(opts);
            if (result.Status != PromptStatus.OK) return;
            var blkOldId = result.ObjectId;

            opts.Message = "\nPlease Select Entity to Replace the orginal Entity : ";
            result = ed.GetEntity(opts);
            if (result.Status != PromptStatus.OK) return;
            var blkNewId = result.ObjectId;

            using (var tr = db.TransactionManager.StartTransaction())
            {
                var blkRefOld = (BlockReference)tr.GetObject(blkOldId, OpenMode.ForWrite);
                var blkRefNew = (BlockReference)tr.GetObject(blkNewId, OpenMode.ForRead);
                blkRefOld.BlockTableRecord = blkRefNew.DynamicBlockTableRecord;

                foreach (ObjectId id in blkRefOld.AttributeCollection)
                {
                    var att = (AttributeReference)tr.GetObject(id, OpenMode.ForWrite);
                    att.Erase();
                }

                RXClass rxclass = RXObject.GetClass(typeof(AttributeDefinition));
                var btr = tr.GetObject(blkRefNew.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;

                if (btr.HasAttributeDefinitions)
                {
                    foreach (ObjectId objId in btr)
                    {
                        if (objId.ObjectClass.IsDerivedFrom(rxclass))
                        {
                            var attDef = tr.GetObject(objId, OpenMode.ForRead) as AttributeDefinition;
                            if (!attDef.Constant)
                            {
                                var attRef = new AttributeReference();
                                attRef.SetAttributeFromBlock(attDef, blkRefOld.BlockTransform);
                                blkRefOld.AttributeCollection.AppendAttribute(attRef);
                                tr.AddNewlyCreatedDBObject(attRef, true);
                            }
                        }
                    }
                }

                tr.Commit();
            }
        }


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes
Message 5 of 6

ilovejingle
Enthusiast
Enthusiast

It mazes me when it works.

What exactly happening in the code?

blkRefOld.BlockTableRecord = blkRefNew.DynamicBlockTableRecord;

 

 

0 Likes
Message 6 of 6

_gile
Consultant
Consultant

A BlockReference is only an inserted reference to a BlockTableRecord.

You can simply change the BlockTableRecord the BlockReference references to.

For dynamic blocks, you have to reference to the DynamicBlockTableRecord (the original definition).



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

0 Likes