Задать дробное свойство динамическому блоку

Автор Тема: Задать дробное свойство динамическому блоку  (Прочитано 7560 раз)

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

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

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
Работаю в autocad2014, задаю дробное (double) значение свойству "Ширина", которое влияет на ширину динамического блока. Автокад просто вылетает без предупреждения. Если перевожу в строку, то выдаёт ошибку. Как правильно делать?
Код - C# [Выбрать]
  1. block.DynamicBlockReferencePropertyCollection[prop_index].Value = value;

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

  • ADN Club
  • *****
  • Сообщений: 624
  • Карма: 158
    • ПГСу Бложик
Если я правильно помню, то там,  по мимо нужных свойств, еще и столько же дополнительных, но в режиме РидОнли. Вполне возможно, что у Вы пытаетесь записать именно в ридОнли сво-во... Лучше тут по имени, в цикле как ниже или Linq запросом.

Код - C# [Выбрать]
  1. Db.DynamicBlockReferencePropertyCollection acBlockDynProp =
  2. acBlRef.DynamicBlockReferencePropertyCollection;
  3. if (acBlockDynProp != null)
  4. {
  5.         foreach (Db.DynamicBlockReferenceProperty obj in acBlockDynProp)
  6.         {
  7.                                                     if (obj.PropertyName == "Distance1")
  8.                                                     {
  9.                                                        acBlRef.UpgradeOpen();
  10.                                                         obj.Value = shirina;
  11.                                                         acBlRef.DowngradeOpen();
  12.  
  13.                                                     }
  14.           }
  15. }
  16.  
Код - vb.net [Выбрать]
  1. Dim acBlockDynProp As DynamicBlockReferencePropertyCollection
  2. acBlockDynProp = acBlock.DynamicBlockReferencePropertyCollection
  3. If acBlockDynProp <> Nothing Then
  4. 'тут я налажал
  5.         Dim acBlockDynProp_vid As IEnumerable(Of Object) = From q In acBlockDynProp Where q.PropertyName.ToString = "ДЛИНА" Select q
  6. End If
« Последнее редактирование: 05-12-2014, 14:54:30 от Boxa.Shu »

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

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
Дополнительных у меня нет (кроме одного - Origin, но я с ним не работаю), в автокаде на панели свойств я значение спокойно меняю.

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

  • ADN Club
  • *****
  • Сообщений: 624
  • Карма: 158
    • ПГСу Бложик
а блок для записи открыт?

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

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
Да, перед этим текстовое свойство вполне себе задаётся нормально.

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

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
А у вас опыт был - дробные числа должны нормально устанавливаться? Или какая-то особенность есть?

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

  • ADN Club
  • *****
  • Сообщений: 624
  • Карма: 158
    • ПГСу Бложик
Нет там никаких особенностей, все параметры там Double и в открытом для записи блоке, нормально меняются.
Наверное следующее сообщение должно быть таким:
Давай код и файл с блоком...

ЗЫ.
Обновил код в первом ответе, только что попробовал, работает отлично. AutoCAD 2014 x64 Win 7

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

  • Administrator
  • *****
  • Сообщений: 13882
  • Карма: 1787
  • Рыцарь ObjectARX
  • Skype: rivilis
Наверное следующее сообщение должно быть таким:
Давай код и файл с блоком...
+1000000
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
А у вас опыт был - дробные числа должны нормально устанавливаться? Или какая-то особенность есть?
У меня есть - дробные устанавливаются (причем если у свойства стоит "шаг округления"- то он и округлит сам - без лишних вопросов, оно-же как и превышение допустимых диапазонов свойства - обработает до ближайшего допустимого).
з.ы. Причем вхождение блока не обязательно открывать для записи - ForRead - достаточно (меняем-то свойство - там по сути вообще новое вхождение будет сгенерировано).

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

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
Что бы избавиться от хитросплетений кода и разных библиотек, я решил сделать пробный метод в отдельном проекте. Что интересно: теперь не срабатывает присвоение даже текстовых полей. Чего-то я, видимо, недопонимаю...
Прикладываю файл с блоком. Код весь тут:
Код - C# [Выбрать]
  1. using System;
  2. using System.Linq;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.Runtime;
  6.  
  7. namespace AutocadTestProject {
  8.     public class AutocadTest : IExtensionApplication {
  9.  
  10.         [CommandMethod("Проба1")]
  11.         public void Test1() {
  12.             var block_name = "PrintRamka";
  13.             var scale = 2;
  14.             var doc = Application.DocumentManager.MdiActiveDocument;
  15.             using (doc.LockDocument()) {
  16.                 using (var tr = doc.TransactionManager.StartTransaction()) {
  17.                     var db = doc.Database;
  18.                     using (var bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable) {
  19.                         using (var space = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord) {
  20.                             var block_id = ObjectId.Null;
  21.                             foreach (var object_id in space) {
  22.                                 using (var obj = tr.GetObject(object_id, OpenMode.ForRead) as BlockReference) {
  23.                                     if (obj == null || !obj.IsDynamicBlock) continue;
  24.                                     using (var block_def = tr.GetObject(obj.DynamicBlockTableRecord, OpenMode.ForRead) as BlockTableRecord) {
  25.                                         if (block_def.Name != block_name) continue;
  26.                                     }
  27.                                 }
  28.                                 block_id = object_id;
  29.                                 break;
  30.                             }
  31.                             if (block_id == ObjectId.Null) {
  32.                                 doc.Editor.WriteMessage("Не найден динамический блок " + block_name);
  33.                                 return;
  34.                             }
  35.                             using (var block = tr.GetObject(block_id, OpenMode.ForWrite) as BlockReference) {
  36.                                 if (block == null || !block.IsDynamicBlock) {
  37.                                     doc.Editor.WriteMessage("Найденный объект не является динамическим блоком");
  38.                                     return;
  39.                                 }
  40.                                 SetBlockProperty(block, "Формат", String.Format("A4"), tr);
  41.                                 SetBlockProperty(block, "Выбор A4", String.Format("A4x2"), tr);
  42.                                 if (scale > 1) {
  43.                                     foreach (var prop_name in new[] {"Высота", "Ширина"}) {
  44.                                         SetBlockProperty(block, prop_name, scale * GetBlockPropertyDouble(block, prop_name), tr);
  45.                                     }
  46.                                 }
  47.                             }
  48.                         }
  49.                     }
  50.                 }
  51.             }
  52.         }
  53.  
  54.         private double GetBlockPropertyDouble(BlockReference block, string prop_name) {
  55.             return (from DynamicBlockReferenceProperty prop in block.DynamicBlockReferencePropertyCollection where String.Compare(prop.PropertyName, prop_name, StringComparison.InvariantCultureIgnoreCase) == 0 select (double) prop.Value).FirstOrDefault();
  56.         }
  57.  
  58.         public void SetBlockProperty(BlockReference block, string prop_name, object value, Transaction trn = null) {
  59.             try {
  60.                 foreach (DynamicBlockReferenceProperty prop in block.DynamicBlockReferencePropertyCollection) {
  61.                     if (String.Compare(prop.PropertyName, prop_name, StringComparison.InvariantCultureIgnoreCase) != 0) continue;
  62.                     prop.Value = value;
  63.                     break;
  64.                 }
  65.             } catch {
  66.                 Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(String.Format("Не удалось изменить свойство \"{0}\"", prop_name));
  67.             }
  68.         }
  69.  
  70.         public void Initialize() {
  71.                
  72.         }
  73.  
  74.         public void Terminate() {
  75.            
  76.         }
  77.     }
  78. }
Работаю с autocad 2014.

Оффлайн bargool

  • ADN Club
  • ***
  • Сообщений: 111
  • Карма: 6
А где коммит транзакции?
И ещё. Моя практика показала, что получение коллекции дин. параметров блока каждый раз, когда хотим получить / поменять очередной параметр у одного и того же блока - очень дорогостоящая операция (правда, у меня было получение десятков параметров для каждого блока, и сотни блоков). Лучше кешировать DynamicBlockReferencePropertyCollection пока работаем с одним блоком.
Алексей

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

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
У меня в библиотеке он делается автоматически, поэтому тут я про него совсем забыл... Да, спасибо! В таком варианте всё нормально срабатывает, после того как я добавил tr.Commit();
Буду разбираться в чём может быть дело в программе...

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

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
Лучше кешировать DynamicBlockReferencePropertyCollection пока работаем с одним блоком.
Спасибо! Подумаю, как это лучше сделать в рамках библиотеки.

Я разобрался в чём было дело. Данный блок в моей программе вставляется в чертёж со свойством DuplicateRecordCloning.Ignore. Оказывается, я в тестовом файле случайно сохранил старый вариант блока, а там свойства ширины и высоты не были выведены для открытого доступа. А я думал, они из-за какой-то ошибки пропадают... :)