Как грамотно выбрать только динамические блоки с конкретными именами?

Автор Тема: Как грамотно выбрать только динамические блоки с конкретными именами?  (Прочитано 7145 раз)

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

Оффлайн Максим МаркевичАвтор темы

  • ADN Club
  • ****
  • Сообщений: 254
  • Карма: 29
  • Skype: evthisrel
Всем привет. Столкнулся с такой задачкой..
Выделяю чертеж, на котором может быть все, что угодно (любые объекты Autocad, прокси и прочее), хочу получить доступ только к динамическим блокам с определенным именем.
Когда задача была получать только динамические блоки, тогда делал я вот так:
Код - C# [Выбрать]
  1. [CommandMethod("Select")]
  2. public void Select()
  3. {
  4.     var doc = Application.DocumentManager.MdiActiveDocument;
  5.     if (doc == null)
  6.         return;
  7.     var db = doc.Database;
  8.     var ed = doc.Editor;
  9.     using (doc.LockDocument())
  10.     {
  11.         using (var tr = db.TransactionManager.StartTransaction())
  12.         {
  13.             var acSelSetPrompt = ed.GetSelection() as PromptSelectionResult;
  14.             if (acSelSetPrompt.Status == PromptStatus.OK)
  15.             {
  16.                 var acSSet = acSelSetPrompt.Value;
  17.                 foreach (SelectedObject acSelSetObj in acSSet)
  18.                 {
  19.                     if (acSelSetObj != null)
  20.                     {
  21.                         var blkRef = tr.GetObject(acSelSetObj.ObjectId, OpenMode.ForWrite) as BlockReference;
  22.                         if (blkRef.IsDynamicBlock == true && blkRef != null)
  23.                         {
  24.                             Application.ShowAlertDialog("Есть!!!");
  25.                         }
  26.                     }
  27.                 }
  28.             }
  29.             tr.Commit();
  30.         }
  31.     }
  32. }
Когда стало необходимо получить динамический блок с конкретным именем, то я добавил следующее:
Код - C# [Выбрать]
  1. [CommandMethod("Select")]
  2. public void Select()
  3. {
  4.     var doc = Application.DocumentManager.MdiActiveDocument;
  5.     if (doc == null)
  6.         return;
  7.     var db = doc.Database;
  8.     var ed = doc.Editor;
  9.     using (doc.LockDocument())
  10.     {
  11.         using (var tr = db.TransactionManager.StartTransaction())
  12.         {
  13.             var acSelSetPrompt = ed.GetSelection() as PromptSelectionResult;
  14.             if (acSelSetPrompt.Status == PromptStatus.OK)
  15.             {
  16.                 var acSSet = acSelSetPrompt.Value;
  17.                 foreach (SelectedObject acSelSetObj in acSSet)
  18.                 {
  19.                     if (acSelSetObj != null)
  20.                     {
  21.                         var blkRef = tr.GetObject(acSelSetObj.ObjectId, OpenMode.ForWrite) as BlockReference;
  22.                         var block = (BlockTableRecord)tr.GetObject(blkRef.DynamicBlockTableRecord, OpenMode.ForRead);
  23.                         if (blkRef.IsDynamicBlock == true && blkRef != null && block.Name == "Имя блока")
  24.                         {
  25.                             Application.ShowAlertDialog("Есть!!!");
  26.                         }
  27.                     }
  28.                 }
  29.             }
  30.             tr.Commit();
  31.         }
  32.     }
  33. }
Ну и что-то не то добавил :), так как, при выделении, например, полилинии, я получаю фатальную ошибку, не могу понять, почему?
Буду рад любой помощи и пояснениям. Заранее, спасибо.

Отмечено как Решение Максим Маркевич 19-08-2016, 23:13:05

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
У тебя же нет проверки на null значения blkRef после строки 21. Если попадает не BlockReference, то значение blkRef становится равным null. Ну и дальше Exception...
И зачем отрываешь ForWrite если не модифицируешь вставку блока?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Максим МаркевичАвтор темы

  • ADN Club
  • ****
  • Сообщений: 254
  • Карма: 29
  • Skype: evthisrel
У тебя же нет проверки на null значения blkRef после строки 21. Если попадает не BlockReference, то значение blkRef становится равным null. Ну и дальше Exception...
Вот же. Стоило поспать, прежде чем тему создавать.  :) Спасибо за оперативность!!
И зачем отрываешь ForWrite если не модифицируешь вставку блока?
В своем коде я модифицирую, для темы делал наглядный пример, не подправил.

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Кстати, еще одно замечание. Такую проверку лучше не делать:
Код - C# [Выбрать]
  1. if (blkRef.IsDynamicBlock == true) {
  2. //...
  3. }
  4.  
Как оказалось не всегда у динамических блоков свойство IsDynamicBlock установлено в true. В частности если у блока разные масштабные коэффициенты по X,Y,Z. При этом во всём остальном поведение блока как у динамического. Я когда-то передавал эту информацию в  Autodesk.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Максим МаркевичАвтор темы

  • ADN Club
  • ****
  • Сообщений: 254
  • Карма: 29
  • Skype: evthisrel
Как оказалось не всегда у динамических блоков свойство IsDynamicBlock установлено в true. В частности если у блока разные масштабные коэффициенты по X,Y,Z. При этом во всём остальном поведение блока как у динамического. Я когда-то передавал эту информацию в  Autodesk.
Да ладно? Сейчас проверю..

Вот это прикол! :)
Спасибо, что предупредили.
Получается, смысл проверки совсем отпадает или можно сделать что-то аналогичное?

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Получается, смысл проверки совсем отпадает или можно сделать что-то аналогичное?
Ну в общем то отпадает. Фактически можешь проверять на количество элементов в коллекции BlockReference.DynamicBlockReferencePropertyCollection - если > 0, то блок динамический.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Максим МаркевичАвтор темы

  • ADN Club
  • ****
  • Сообщений: 254
  • Карма: 29
  • Skype: evthisrel
Фактически можешь проверять на количество элементов в коллекции BlockReference.DynamicBlockReferencePropertyCollection - если > 0, то блок динамический.
Точно!! Спасибо. :)