更新图纸空间 autocad c# 中的属性

Update attributes in paperspace autocad c#

我正在尝试更新图纸空间中某些属性的值。该块及其属性可在多种布局中找到。我已经尝试了下面发布的代码,但我从 AttributeCollection 中得到了 NullReferenceException。该块被插入到图纸布置中。有人可以指出正确的方向如何解决这个问题或我做错了什么吗?提前致谢!

namespace InvullenKleinTitelhoek
    {
        public class Class2
        {
            [CommandMethod("KleineTitelhoekbis")]
            public void UpdateBlockAttributes()
            {
                Document doc = Application.DocumentManager.MdiActiveDocument;
                Database db = doc.Database;
                Editor edt = doc.Editor;
        
                //To change 
                //blockname     TBM_DATA04_S_N
                //att           AT_DATA_DESC3_S_N
                //att           AT_DATA_DESC4_S_N"




                //-----------------------------------------------------------------//

                PromptStringOptions lijnDrie = new PromptStringOptions("Lijn 3");
                lijnDrie.AllowSpaces = true;

                PromptResult textStringLijnDrie = edt.GetString(lijnDrie);
                string stLijnDrie = textStringLijnDrie.StringResult;

                PromptStringOptions lijnVier = new PromptStringOptions("Lijn 4");
                lijnVier.AllowSpaces = true;

                PromptResult textStringLijnVier = edt.GetString(lijnVier);
                string stLijnVier = textStringLijnVier.StringResult;


                //-----------------------------------------------------------------//


                using (Transaction trans = db.TransactionManager.StartTransaction())
                {
                    try
                    {
                        DBDictionary layoutDict = trans.GetObject(db.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
                
                        foreach(DBDictionaryEntry entry in layoutDict)
                        {
                            Layout ltr = (Layout)trans.GetObject((ObjectId)entry.Value, OpenMode.ForWrite);

                            BlockTable bt = trans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                            BlockTableRecord btr = trans.GetObject(bt[BlockTableRecord.PaperSpace], OpenMode.ForRead) as BlockTableRecord;

                            foreach (ObjectId id in btr)
                            {
                                DBObject obj = trans.GetObject(id, OpenMode.ForRead);
                                BlockReference br = obj as BlockReference;

                                AttributeCollection attCol = br.AttributeCollection;

                                foreach (ObjectId objId in attCol)
                                {
                                    DBObject dbobj = trans.GetObject(objId, OpenMode.ForRead) as DBObject;

                                    AttributeReference attRef = dbobj as AttributeReference;



                                    if (attRef.Tag == "AT_DATA_DESC3_S_N")
                                    {
                                        attRef.UpgradeOpen();
                                        attRef.TextString = stLijnDrie;
                                
                                    }

                                    if (attRef.Tag == "AT_DATA_DESC4_S_N")
                                    {
                                        attRef.UpgradeOpen();
                                        attRef.TextString = stLijnVier;

                                    }


                                }
                        
                            }

                            trans.Commit();

                        }

                




                    }

                    catch (System.Exception ex)
                    {
                        edt.WriteMessage("error:  " + ex.Message);
                    }

                }

            }
        }
    }

好问题

代码有一些错误

  1. 需要检查空属性集合
  2. 需要处理布局上有非块的对象的情况(转换为块将失败)
  3. 需要将 trans.Commit 语句移出所有循环

这是更新后的代码。
需要注意的一件事是,此代码只会在命令启动时更新当前活动的图纸空间选项卡上的块。
即使它遍历所有布局选项卡,它也不会更新所有布局。

        public void UpdateBlockAttributes()
    {
        Document doc = Application.DocumentManager.MdiActiveDocument;
        Database db = doc.Database;
        Editor edt = doc.Editor;
        PromptStringOptions lijnDrie = new PromptStringOptions("Lijn 3");
        lijnDrie.AllowSpaces = true;
        PromptResult textStringLijnDrie = edt.GetString(lijnDrie);
        string stLijnDrie = textStringLijnDrie.StringResult;
        PromptStringOptions lijnVier = new PromptStringOptions("Lijn 4");
        lijnVier.AllowSpaces = true;
        PromptResult textStringLijnVier = edt.GetString(lijnVier);
        string stLijnVier = textStringLijnVier.StringResult;

        // The document must be locked before making modifications
        using (DocumentLock @lock = doc.LockDocument)
        {
            using (Transaction trans = db.TransactionManager.StartTransaction())
            {
                try
                {
                    DBDictionary layoutDict = trans.GetObject(db.LayoutDictionaryId, OpenMode.ForWrite) as DBDictionary;
                    string originalLayout = LayoutManager.Current.CurrentLayout;
                    foreach (DBDictionaryEntry entry in layoutDict)
                    {
                        Layout ltr = (Layout)trans.GetObject((ObjectId)entry.Value, OpenMode.ForWrite);
                        string layoutName = ltr.LayoutName;
                        BlockTable bt = trans.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable;
                        BlockTableRecord btr = trans.GetObject(bt(BlockTableRecord.PaperSpace), OpenMode.ForWrite) as BlockTableRecord;
                        if (!layoutName.Equals("Model"))
                        {
                            // Set layout as current so code can modify block attributes on the layout
                            LayoutManager.Current.CurrentLayout = layoutName;
                            edt.WriteMessage("layout name:  " + layoutName + Constants.vbLf);
                            foreach (ObjectId id in btr)
                            {
                                DBObject obj = trans.GetObject(id, OpenMode.ForWrite);
                                Entity entity = obj as Entity;
                                string ownerName = entity.BlockName;
                                BlockReference br = obj as BlockReference;
                                // If cast to block succeeded
                                if (br != null)
                                {
                                    string blockName = br.Name;
                                    AttributeCollection attCol = br.AttributeCollection;
                                    edt.WriteMessage("block name:  " + blockName + Constants.vbLf);
                                    // If block has attributes
                                    if (attCol != null & attCol.Count > 0)
                                    {
                                        foreach (ObjectId objId in attCol)
                                        {
                                            DBObject dbobj = trans.GetObject(objId, OpenMode.ForWrite) as DBObject;
                                            AttributeReference attRef = dbobj as AttributeReference;

                                            if (attRef.Tag == "AT_DATA_DESC3_S_N")
                                            {
                                                edt.WriteMessage("edited att value for:  " + attRef.Tag + Constants.vbLf);
                                                attRef.UpgradeOpen();
                                                attRef.TextString = stLijnDrie;
                                            }

                                            if (attRef.Tag == "AT_DATA_DESC4_S_N")
                                            {
                                                edt.WriteMessage("edited att value for:  " + attRef.Tag + Constants.vbLf);
                                                attRef.UpgradeOpen();
                                                attRef.TextString = stLijnVier;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    LayoutManager.Current.CurrentLayout = originalLayout;
                    // Transaction needs to be outside of loop where code is doing modifications, otherwise it will be closed on commit
                    // causing error mesasge "Operation is not valid due to the current state of the object."
                    trans.Commit();
                }
                catch (Exception ex)
                {
                    edt.WriteMessage("error:  " + ex.Message + Constants.vbLf);
                }
            }
        }
    }