Чтение и запись атрибутов BlockReference

Автор Тема: Чтение и запись атрибутов BlockReference  (Прочитано 14067 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн JohnLenninАвтор темы

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Коллеги!
Не совсем (вернее совсем не) понимаю как извлечь данные из AttributeCollection конкретного BlockReference. По хорошему хотелось бы достать как-то из нее (AttributeCollection) tag и value конкретного атрибута выбранной BlockReference.
Ссылку блока я умею выбирать, умею даже распознавать обычный это блок или динамический, хотелось бы узнать как можно извлечь данные по атрибутам заданной ссылки блока и желательно еще и их поменять.
AttributeCollection я вроде как извлекаю, но что с ней дальше делать ума не приложу. Посомотрел документацию ObjectARX, там нашел такой класс:
Код - C# [Выбрать]
  1. public AttributeReference();
  2. public AttributeReference(
  3.     Point3d position,
  4.     string value,
  5.     string tag,
  6.     ObjectId style
  7. );
  8.  
Только не понимаю как его вытащить из AttributeCollection конкретного экземпляра BlockReference и тот ли этот класс, который мне нужен.
Подскажите где искать?
« Последнее редактирование: 24-02-2016, 18:11:03 от JohnLennin »

Отмечено как Решение JohnLennin 24-02-2016, 15:35:06

Оффлайн Вильдар

  • ADN Club
  • ****
  • Сообщений: 409
  • Карма: 77
  • Skype: vildar82
Re: Чтение и запись атрибутов BlockReference
« Ответ #1 : 24-02-2016, 13:12:56 »
Атрибуты во вхождении блока.
Код - C# [Выбрать]
  1.             foreach (ObjectId idAtrRef in blRef.AttributeCollection)
  2.             {
  3.                using (var atrRef = idAtrRef.Open(OpenMode.ForRead, false, true) as AttributeReference)
  4.                {
  5.                   if (atrRef != null)
  6.                   {                    
  7.                      // atrRef.Tag
  8.                      // atrRef.TextString                    
  9.                   }
  10.                }
  11.             }
Еще, бывает, что нужно проверять, есть ли константные атрибуты у блока
Код - C# [Выбрать]
  1.              using (var btr = idBtr.Open( OpenMode.ForRead) as BlockTableRecord)
  2.             {
  3.                foreach (var idEnt in btr)
  4.                {
  5.                   using (var atr = idEnt.Open( OpenMode.ForRead, false, true)as AttributeDefinition)
  6.                   {
  7.                      if (atr == null || !atr.Constant) continue;
  8.                      // atrRef.Tag
  9.                      // atrRef.TextString  
  10.                   }
  11.                }              
  12.             }

Вырвал пример у себя. Возможно неудачный. Использовать ли транзакцию или нет, ты сам смотри.

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 624
  • Карма: 158
    • ПГСу Бложик
Re: Чтение и запись атрибутов BlockReference
« Ответ #2 : 24-02-2016, 14:43:42 »
А мне больше Linq вариант нравиться, как то так...
Извините, вам запрещён просмотр содержимого спойлеров.

Спрятал неправильный код под спойлер.
« Последнее редактирование: 24-02-2016, 15:50:32 от Boxa.Shu »

Оффлайн Вильдар

  • ADN Club
  • ****
  • Сообщений: 409
  • Карма: 77
  • Skype: vildar82
Re: Чтение и запись атрибутов BlockReference
« Ответ #3 : 24-02-2016, 14:51:05 »
Boxa.Shu, что-то не врублюсь. А где получение атрибута из его id? AttributeCollection ведь содержит id.

Оффлайн JohnLenninАвтор темы

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Re: Чтение и запись атрибутов BlockReference
« Ответ #4 : 24-02-2016, 15:36:40 »
Коллеги! Спасибо огромное за помощь. Все оказывается настолько просто. Вот я глупый, не догадался!
Спасибо еще раз за помощь!

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 624
  • Карма: 158
    • ПГСу Бложик
Re: Чтение и запись атрибутов BlockReference
« Ответ #5 : 24-02-2016, 15:47:18 »
Boxa.Shu, что-то не врублюсь. А где получение атрибута из его id? AttributeCollection ведь содержит id.
прошу прощения, это я виноват, не тот фрагмент выдрал и не из того проекта.. =(
Вот правильный код:
Код - C# [Выбрать]
  1. [Rtm.CommandMethod("GetAttr")]
  2. static public void GetAttr()
  3. {
  4.  
  5.     App.Document acDoc = App.Application.DocumentManager.MdiActiveDocument;
  6.     Db.Database acCurDb = acDoc.Database;
  7.     Ed.Editor acEd = acDoc.Editor;
  8.  
  9.     Ed.PromptEntityOptions proO = new Ed.PromptEntityOptions("\n Выбери блок");
  10.     Ed.PromptEntityResult proR = acEd.GetEntity(proO);
  11.     using (Db.Transaction acTrans = acCurDb.TransactionManager.StartOpenCloseTransaction())
  12.     {
  13.         Db.BlockTable acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, Db.OpenMode.ForRead) as Db.BlockTable;
  14.         Db.BlockReference blr = acTrans.GetObject(proR.ObjectId, Db.OpenMode.ForRead) as Db.BlockReference;
  15.         Db.BlockTableRecord btr = acTrans.GetObject(acBlkTbl[blr.Name], Db.OpenMode.ForRead) as Db.BlockTableRecord;
  16.         if (btr.HasAttributeDefinitions)
  17.         {
  18.             Db.AttributeReference blockAttr = ((from Db.ObjectId attribRefId in blr.AttributeCollection
  19.                                                 let attribRef = (Db.AttributeReference)acTrans.GetObject(attribRefId, Db.OpenMode.ForRead)
  20.                                                 where attribRef.Tag.Equals("высота", StringComparison.OrdinalIgnoreCase)
  21.                                                 select attribRef).FirstOrDefault()) as Db.AttributeReference;
  22.         }
  23.     };
  24. }
  25.  

Оффлайн JohnLenninАвтор темы

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Re: Чтение и запись атрибутов BlockReference
« Ответ #6 : 24-02-2016, 17:37:02 »
Попробую и этот код.
Хотя тот код тоже работает, правда компилятор обзывает этот сопособ анахронизмом :)
Цитировать
warning CS0618: 'Autodesk.AutoCAD.DatabaseServices.ObjectId.Open(Autodesk.AutoCAD.DatabaseServices.OpenMode, bool, bool)' is obsolete: 'For advanced use only. Use GetObject instead'
Предлагает использовать GetObject.
Наверное надо было по фэншую написать вот так:
Код - C# [Выбрать]
  1.  using (var atrRef = idAtrRef.GetObject (OpenMode.ForRead) as AttributeReference)
  2.  
вместо
Код - C# [Выбрать]
  1. using (var atr = idEnt.Open( OpenMode.ForRead, false, true)as AttributeDefinition)
  2.  
Тогда компилятор не выдает предупреждений.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Чтение и запись атрибутов BlockReference
« Ответ #7 : 24-02-2016, 18:10:36 »
Это не анахронизм - это для advanced. Чувствуешь разницу?  :)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн JohnLenninАвтор темы

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Re: Чтение и запись атрибутов BlockReference
« Ответ #8 : 24-02-2016, 18:12:17 »
А, ну понял, для продвинутых олдфагов  ;D ;D

Оффлайн Вильдар

  • ADN Club
  • ****
  • Сообщений: 409
  • Карма: 77
  • Skype: vildar82
Re: Чтение и запись атрибутов BlockReference
« Ответ #9 : 24-02-2016, 19:23:33 »
Больной вопрос с транзакциями и без. По ситуации нужно ориентироваться. Обычно использую Open, когда только читаю и не очень много.

Оффлайн JohnLenninАвтор темы

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Re: Чтение и запись атрибутов BlockReference
« Ответ #10 : 25-02-2016, 10:07:49 »
Еще такой вопрос в догонку - данный способ не извлекает атрибуты из вставок динамических блоков, хотя в свойствах они есть и отображаются. Каким способом их вытащить, если это динамический блок?
В DynamicBlockReferencePropertyCollection содержится только текущее представление динамического блока, и больше ничего, а в BlockReference.AttributeCollection пусто. Как быть?

Оффлайн Вильдар

  • ADN Club
  • ****
  • Сообщений: 409
  • Карма: 77
  • Skype: vildar82
Re: Чтение и запись атрибутов BlockReference
« Ответ #11 : 25-02-2016, 10:12:29 »
Извлекает! AttributeCollection - для BlockReference, выдает атрибуты, независимо от динамики.
Возможно у тебя динамика блока выполнена некорректно. Возможно используется видимость, и в одной из них не показываются атрибуты. Такое может быть!

Оффлайн Владимир Шу

  • ADN Club
  • *****
  • Сообщений: 624
  • Карма: 158
    • ПГСу Бложик
Re: Чтение и запись атрибутов BlockReference
« Ответ #12 : 25-02-2016, 10:14:00 »
Как быть?
Если вопрос мне, то ответ где то тут:
Код - C# [Выбрать]
  1.         /// <summary>
  2.         /// Метод который проходится по списку паттернов блоков и
  3.         /// заполняет ВСЕ поля и свойства в объекте block
  4.         /// </summary>
  5.         /// <param name="acCurDb">Текущщая база чертежа</param>
  6.         /// <param name="BlockID">Db.ObjectId выбранного пользователем блока</param>
  7.         private static void UpdateBlockList(Db.Database acCurDb, Db.ObjectId BlockID)
  8.         {
  9.  
  10.             ////Создаю объект содержищий имена дин. свойств и теги
  11.             ////аттрибутов выбранного пользователем блока
  12.             //SelectelBlockProp = new SelectelBlockProperty();
  13.  
  14.             // Пройтись по списку блоков и наполнить их смыслом
  15.             // Получить значения атрибутов и динамических свойств для выбранного блока.
  16.             using (Db.Transaction acTrans = acCurDb.TransactionManager.StartOpenCloseTransaction())
  17.             {
  18.  
  19.                 Db.BlockReference acBlock = (Db.BlockReference)acTrans.GetObject(BlockID, Db.OpenMode.ForRead);
  20.                 Db.BlockTableRecord blr;
  21.                 if (acBlock.IsDynamicBlock)
  22.                 {
  23.                     blr = (Db.BlockTableRecord)acTrans.GetObject(acBlock.DynamicBlockTableRecord, Db.OpenMode.ForRead);
  24.                 }
  25.                 else
  26.                 {
  27.                     blr = (Db.BlockTableRecord)acTrans.GetObject(acBlock.BlockTableRecord, Db.OpenMode.ForRead);
  28.                 }
  29.  
  30.                 foreach (block blk in blkList)
  31.                 {
  32.                     if (acBlock.IsDynamicBlock)
  33.                     {
  34.                         foreach (KeyValuePair<string, Double> j in blk._DynProp.ToList())
  35.                         {
  36.                             //Ищим значение динамического сво-ва
  37.                             Db.DynamicBlockReferenceProperty blockReferenceProperty = (
  38.                                 (from Db.DynamicBlockReferenceProperty blockRefProperty in acBlock.DynamicBlockReferencePropertyCollection
  39.                                  where blockRefProperty.PropertyName.Equals(j.Key, StringComparison.OrdinalIgnoreCase)
  40.                                  select blockRefProperty).FirstOrDefault()) as Db.DynamicBlockReferenceProperty;
  41.  
  42.                             Double prop = 0;
  43.                             Double.TryParse(blockReferenceProperty.Value.ToString(), out prop);
  44.                             blk._DynProp[j.Key] = prop;
  45.  
  46.                             // Ищим индекс динамического свойства по имени
  47.                             //int DynPropIndex = GetNumberDynProp(acCurDb, BlockID, j.Key);
  48.                             KeyValuePair<string, int> DynPropIndex = GetNumberDynProp(acCurDb, BlockID, j.Key);
  49.                             blk._DynPropID[j.Key] = DynPropIndex.Value;
  50.                             blk._DynPropConnectionName[j.Key] = DynPropIndex.Key;
  51.                         }
  52.                     }
  53.  
  54.                     if (blr.HasAttributeDefinitions)
  55.                     {
  56.                         foreach (KeyValuePair<string, string> j in blk._AttProp.ToList())
  57.                         {
  58.                             //Ищим записи и свойства аттрибута
  59.                             Db.AttributeReference blockAttr = ((from Db.ObjectId attribRefId in acBlock.AttributeCollection
  60.                                                                 let attribRef = (Db.AttributeReference)acTrans.GetObject(attribRefId, Db.OpenMode.ForRead)
  61.                                                                 where attribRef.Tag.Equals(j.Key, StringComparison.OrdinalIgnoreCase)
  62.                                                                 select attribRef).FirstOrDefault()) as Db.AttributeReference;
  63.                             if (blockAttr != null)
  64.                             {
  65.                                 blk._AttProp[j.Key] = blockAttr.TextString;
  66.                                 blk._AttPropID[j.Key] = blockAttr.ObjectId;
  67.                             }
  68.                         }
  69.                     }
  70.                 }
  71.                 acTrans.Commit();
  72.             }
  73.  
  74.         }
  75.  

Оффлайн JohnLenninАвтор темы

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Re: Чтение и запись атрибутов BlockReference
« Ответ #13 : 25-02-2016, 10:22:45 »
Точно извлекает. Прошу прощения. У меня просто атрибуты были скрытые, а в условиях стояло отобразить только видимые. Все работает. Всем еще раз спасибо!!!

Оффлайн JohnLenninАвтор темы

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Re: Чтение и запись атрибутов BlockReference
« Ответ #14 : 26-02-2016, 11:39:01 »
Потестировав код, увидел, что если извлекать атрибуты из динамического блока таким же способом, что и для обычного блока, то вываливыаются все атрибуты для всех блоков, которые входят в динамический блок и понять какой из них применим для текущего вида димаического блока мне не удалось.
Попробовал написать такой код, в котором из всех представлений динамического блока (br) я выбираю видимую selectedBlock, однако у него атрибутов нет, хотя в свойствах у текущего представления блока они есть и редактируются. Может как-то не так извлек? Когда блок обычный все работает (после 75 строки).

Код - C# [Выбрать]
  1.                
  2.                 using (Transaction tr = MainMod.CurrentDocument.Database.TransactionManager.StartTransaction())
  3.                 {
  4.                     foreach (long BlockRefID in blocks)
  5.                    
  6.                     {
  7.                         // Получаем ссылки на блоки во всех их видах
  8.                         BlockReference br = null;
  9.                         Handle h = new Handle(BlockRefID);
  10.                         ObjectId id;
  11.                         if (MainMod.CurrentDocument.Database.TryGetObjectId(h, out id))
  12.                         {
  13.                             br = id.GetObject(OpenMode.ForRead) as BlockReference;
  14.                         }
  15.                         if (br == null)
  16.                         {
  17.                             continue;
  18.                         }
  19.                         if (br.IsDynamicBlock)
  20.                         {
  21.                             // блок динамический
  22.                             // выбираем видимый блок (selectedBlock) из представлений динамического блока
  23.                             MainMod.CurrentDocument.Editor.WriteMessage("Блок динамический \n");
  24.                             BlockReference selectedBlock = null;
  25.  
  26.                             BlockTableRecord btr = null;
  27.                             if (br.BlockTableRecord != ObjectId.Null)
  28.                             {
  29.                                 btr = br.BlockTableRecord.GetObject(OpenMode.ForRead) as BlockTableRecord;
  30.                             }
  31.                            
  32.                             if (btr != null)
  33.                             {
  34.                                 // получаем видимый в данный момент блок из всех, которые есть в динамическом
  35.                                 // смотрим все представления динамического блока
  36.                                 foreach (ObjectId element in btr)
  37.                                 {
  38.                                     BlockReference currentbr = element.GetObject(OpenMode.ForRead) as BlockReference;
  39.                                     // выбираем непустое и видимое
  40.                                     if (currentbr != null && currentbr.Visible)
  41.                                     {
  42.                                         selectedBlock = currentbr;
  43.                                     }
  44.                                 }// получили selectedBlock
  45.                             } // if btr !=null
  46.                            
  47.                             if (selectedBlock != null)
  48.                             {
  49.                                 AttributeCollection attrC = null;
  50.                                 string blockName = selectedBlock.Name;
  51.                                 string blockLayer = selectedBlock.Layer;
  52.                                 attrC = selectedBlock.AttributeCollection;
  53.                                 MainMod.CurrentDocument.Editor.WriteMessage("Количество атрибутов: " + attrC.Count + "\n");
  54.                                 if (attrC.Count > 0)
  55.                                 {
  56.                                     foreach (ObjectId idAtrRef in attrC)
  57.                                     {
  58.                                         using (var atrRef = idAtrRef.GetObject(OpenMode.ForRead) as AttributeReference)
  59.                                         {
  60.                                             if (atrRef != null)
  61.                                             {
  62.                                                 MainMod.CurrentDocument.Editor.WriteMessage("Тэг атрибута: " + atrRef.Tag + "\n");
  63.                                                 MainMod.CurrentDocument.Editor.WriteMessage("Значение атрибута: " + atrRef.TextString + "\n");
  64.                                             }
  65.                                         }
  66.                                     }
  67.                                 }
  68.                                 MainMod.CurrentDocument.Editor.WriteMessage("Имя блока :" + blockName + "\n");
  69.                                 MainMod.CurrentDocument.Editor.WriteMessage("Слой :" + blockLayer + "\n");
  70.                             } // if selectedBlock != null
  71.  
  72.  
  73.  
  74.                         }
  75.                         else
  76.                         {
  77.                             // блок обычный
  78.                             AttributeCollection attrC = null;
  79.                             string blockName = br.Name;
  80.                             string blockLayer = br.Layer;
  81.                             attrC = br.AttributeCollection;
  82.                             if (attrC.Count > 0)
  83.                             {
  84.                                 foreach (ObjectId idAtrRef in attrC)
  85.                                 {
  86.                                     using (var atrRef = idAtrRef.GetObject(OpenMode.ForRead) as AttributeReference)
  87.                                     {
  88.                                         if (atrRef != null)
  89.                                         {
  90.                                             MainMod.CurrentDocument.Editor.WriteMessage("Тэг атрибута: " + atrRef.Tag + "\n");
  91.                                             MainMod.CurrentDocument.Editor.WriteMessage("Значение атрибута: " + atrRef.TextString + "\n");
  92.                                         }
  93.                                     }
  94.                                 }
  95.                             }
  96.                             MainMod.CurrentDocument.Editor.WriteMessage("Имя блока :" + blockName  + "\n");
  97.                             MainMod.CurrentDocument.Editor.WriteMessage("Слой :" + blockLayer  + "\n");
  98.  
  99.                         }
  100.                     } // foreach
  101.                 } // tr