PaletteSet и и групповое изменение свойств примитивов

Автор Тема: PaletteSet и и групповое изменение свойств примитивов  (Прочитано 6392 раз)

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

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

  • ADN OPEN
  • Сообщений: 46
  • Карма: 1
Всем добрый день! Начал разбираться с палитрой, нашел на форуме пример Дмитрия Загорулькина, где он показал как можно организовать с помощью PaletteSet групповое изменение координат X, Y, Z и радиуса нескольких окружностей сразу. При этом если выделяются несколько окружностей и у них разные значения каких-то переменных, то в TextBox, расположенного на созданной палитре выводится сообщения "РАЗЛИЧНЫЕ". Попытался данный код переделать под свои нужды, но у меня есть переменные как числовые, так и текстовые, которые выводятся в TextBox. С числовыми переменными, которые берутся из расширенных данных полилинии все замечательно, данный код работает. А вот с текстовыми никак не получается  - всегда выводится ноль. Перепробовал кучу вариантов - победить не могу. Просьба ко всем, а особенно к Дмитрию, помогите, пните в нужном направлении, что нужно поменять в коде? Прикладываю код со своими изменениями и DWG файл в полилиниями, у которых есть расширенные данные.

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Код - XML [Выбрать]
  1. <local:DoubleTextBox Grid.Column="1" Value="{Binding CoordNameXR}"/>
  2. <local:DoubleTextBox Grid.Row="1" Grid.Column="1" Value="{Binding CoordNumberXR}"/>
  3. <local:DoubleTextBox Grid.Row="2" Grid.Column="1" Value="{Binding CoordLength1}"/>
  4. <local:DoubleTextBox Grid.Row="3" Grid.Column="1" Value="{Binding CoordLength2}"/>
  5. <local:DoubleTextBox Grid.Row="4" Grid.Column="1" Value="{Binding CoordWidth}"/>
  6. <local:DoubleTextBox Grid.Row="5" Grid.Column="1" Value="{Binding CoordDepth}"/>
  7. <local:DoubleTextBox Grid.Row="6" Grid.Column="1" Value="{Binding CoordSandLlayer}"/>
  8. <TextBox Grid.Row="7" Grid.Column="1" Text="{Binding CoordNumberXR}"/>
Так всё верно, так и будет. В примере реализован контрол для изменения числовых параметров, с названием DoubleTextBox. Его поведение именно такое - он корректно работает только с числами. Для работы с текстовыми параметрами, надо реализовать его аналог для строковых данных - StringTextBox и использовать его. Разумеется, для его работы понадобятся дополнительные конвертеры и валидаторы для строковых значений.

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

  • ADN OPEN
  • Сообщений: 46
  • Карма: 1
Код - XML [Выбрать]
  1. <local:DoubleTextBox Grid.Column="1" Value="{Binding CoordNameXR}"/>
  2. <local:DoubleTextBox Grid.Row="1" Grid.Column="1" Value="{Binding CoordNumberXR}"/>
  3. <local:DoubleTextBox Grid.Row="2" Grid.Column="1" Value="{Binding CoordLength1}"/>
  4. <local:DoubleTextBox Grid.Row="3" Grid.Column="1" Value="{Binding CoordLength2}"/>
  5. <local:DoubleTextBox Grid.Row="4" Grid.Column="1" Value="{Binding CoordWidth}"/>
  6. <local:DoubleTextBox Grid.Row="5" Grid.Column="1" Value="{Binding CoordDepth}"/>
  7. <local:DoubleTextBox Grid.Row="6" Grid.Column="1" Value="{Binding CoordSandLlayer}"/>
  8. <TextBox Grid.Row="7" Grid.Column="1" Text="{Binding CoordNumberXR}"/>
Так всё верно, так и будет. В примере реализован контрол для изменения числовых параметров, с названием DoubleTextBox. Его поведение именно такое - он корректно работает только с числами. Для работы с текстовыми параметрами, надо реализовать его аналог для строковых данных - StringTextBox и использовать его. Разумеется, для его работы понадобятся дополнительные конвертеры и валидаторы для строковых значений.
Есть пример создания такого текстового контрол?

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

  • ADN OPEN
  • Сообщений: 46
  • Карма: 1
Сделал новый элемент StringTextBox. Показывает теперь все расширенные данные полилинии как и задумывалось. Но вот сохранение изменений не работает правильно. Если изменить какой-нибудь параметр и нажать Enter, то вернется старое значение. И в самой полилинии, в расширенных данных, ничего не измениться. Если сделать изменение параметра и передвинуть мышку за границы Палитры, то в TextBoxe появится старое значение, а по факту изменение записалось. Как победить такую ошибку, в каком методе копать?. Пробывал убирать using (DocumentLock dockLock = adoc.LockDocument()), не помогло, в TextBoxe измененное значение остается, но по факту сохранения не происходит. Прикладываю весь код (в архиве) и видео с проблемой.
Код - C# [Выбрать]
  1. void ChangeCircleCoord(double length1, double length2, double widthXR, double depthXR, double sandLlayerXR)
  2.         {
  3.             if (!IsValid) return;
  4.            
  5.             Document adoc = Application.DocumentManager.MdiActiveDocument;
  6.             if (adoc == null) return;
  7.             Database db = adoc.Database;
  8.            
  9.             using (DocumentLock dockLock = adoc.LockDocument())
  10.             {
  11.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  12.                 {
  13.                     Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\nНачинаю запись изменений......");
  14.                     DBObject dbObj = tr.GetObject(_circleId, OpenMode.ForRead);
  15.                     ObjectId surId = dbObj.ExtensionDictionary;
  16.  
  17.                     DBDictionary dbExt = (DBDictionary)tr.GetObject(surId, OpenMode.ForWrite);
  18.                     ObjectId dId = dbExt.GetAt("ESMT_LEP_v1.0");
  19.                     Xrecord xr = (Xrecord)tr.GetObject(dId, OpenMode.ForWrite);
  20.                     TypedValue[] arr = xr.Data.AsArray();
  21.                     XElement xml_att = XElement.Parse((string)arr[0].Value);
  22.                     //xml_att.SetElementValue("Number", numberXR);
  23.                     //xml_att.SetElementValue("Name", nameXR);
  24.  
  25.                     if (xml_att.Name.ToString() == "Conductor")
  26.                     {
  27.                         xml_att.SetElementValue("AdditionalLength1", Convert.ToString(length1));
  28.                         xml_att.SetElementValue("AdditionalLength2", Convert.ToString(length2));
  29.                     }
  30.  
  31.                     if (xml_att.Name.ToString() == "Trench")
  32.                     {
  33.                         xml_att.SetElementValue("Width", Convert.ToString(widthXR)); //Ширина траншеи
  34.                         xml_att.SetElementValue("Depth", Convert.ToString(depthXR)); //Глубина траншеи
  35.                         xml_att.SetElementValue("SandLlayer", Convert.ToString(sandLlayerXR)); //Слой песка
  36.                     }
  37.  
  38.                     Xrecord xRec = new Xrecord();
  39.                     dbExt.Remove("ESMT_LEP_v1.0");
  40.                     xRec.Data = new ResultBuffer(new TypedValue(1, xml_att));
  41.                     dbExt.SetAt("ESMT_LEP_v1.0", xRec);
  42.                     tr.AddNewlyCreatedDBObject(xRec, true);
  43.  
  44.                     tr.Commit();
  45.                     Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage("\nСохранение изменений выполнено");
  46.                 }
  47.             }
  48.             Autodesk.AutoCAD.Internal.Utils.FlushGraphics();
  49.             Autodesk.AutoCAD.Internal.Utils.SetFocusToDwgView();
  50.         }
  51.  

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Есть пример создания такого текстового контрол?
Есть же пример создания контрола для числа. Для текста делается аналогично, он не сложнее будет в реализации.
Примера не будет, т.к. в моём "боевом" коде я всё давно переделал, использую теперь другой подход. Для новичка там будет сложно разобраться - в полный рост используется рефлексия и обобщения.
Сделал новый элемент StringTextBox.
Не нашёл его в решении из приложенного архива. В AcObjPropPaletteSample/CirclesEditor.xaml закомментированные две строчки с ним, и больше ничего. Не тот код приложен?
Но вот сохранение изменений не работает правильно.
В изначальном примере правильно работало? Если да, то ищите в тех местах, в которые изменения вносили. Изменения надо вносить осторожно, не нарушая цепочки передачи значения, с полным пониманием того, что делаете.
Код глянул мельком. Очень тяжело читается. Надо навести в нём порядок. Хотя бы наименования привести в соответствие с изменениями. Например, если метод называется ChangeCircleCoord, то он должен работать с координатами окружности, а у него внутри совершенно другое. Так надо и переименовать в соответствии с тем, что он теперь делает. И это касается методов, переменных, параметров и прочего.

Оффлайн Lemieux

  • ADN OPEN
  • ****
  • Сообщений: 384
  • Карма: 21
в полный рост используется рефлексия и обобщения
А что в этом сложного для новичка?

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

  • ADN OPEN
  • Сообщений: 46
  • Карма: 1
Новый элемент StrinrTextBox я не приложил специально, так поля не обновлялись при старом DoubleTextBox, я посчитал что с DoubleTextBox будет проще найти в чем дело, где ошибка. Проблему я решил путем добавления в Coord...  пары строк:
 _numberXR = value; в файле "CirclePropData.cs"
и в Coord...
 OnPropertyChanged(new PropertyChangedEventArgs("CoordNameXR")); в файле "CirclesSummaryProps.cs". При этом происходит двойное презаписывание измененных данных. Не знаю правильно это или нет, но так все работает.
Код - C# [Выбрать]
  1. //В файле "CirclePropData.cs":
  2. public string CoordNumberXR
  3.         {
  4.             get { return _numberXR; }
  5.             set
  6.             {
  7.                 Document adoc = Application.DocumentManager.MdiActiveDocument;
  8.                 if (adoc == null) return;
  9.                 Database db = adoc.Database;
  10.  
  11.                 using (DocumentLock dockLock = adoc.LockDocument())
  12.  
  13.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  14.                 {
  15.                     DBObject dbObj = tr.GetObject(_circleId, OpenMode.ForWrite);
  16.                     ObjectId surId = dbObj.ExtensionDictionary;
  17.  
  18.                     DBDictionary dbExt = (DBDictionary)tr.GetObject(surId, OpenMode.ForWrite);
  19.                     ObjectId dId = dbExt.GetAt("ESMT_LEP_v1.0");
  20.                     Xrecord xr = (Xrecord)tr.GetObject(dId, OpenMode.ForWrite);
  21.                     TypedValue[] arr = xr.Data.AsArray();
  22.                     XElement xml_att = XElement.Parse((string)arr[0].Value);
  23.                     xml_att.SetElementValue("Number", value);
  24.                     _numberXR = value;
  25.                     Xrecord xRec = new Xrecord();
  26.                     dbExt.Remove("ESMT_LEP_v1.0");
  27.                     xRec.Data = new ResultBuffer(new TypedValue(1, xml_att));
  28.                     dbExt.SetAt("ESMT_LEP_v1.0", xRec);
  29.                     tr.AddNewlyCreatedDBObject(xRec, true);
  30.  
  31.                     tr.Commit();
  32.                 }
  33.  
  34.                 Autodesk.AutoCAD.Internal.Utils.FlushGraphics();
  35.             }
  36.         }
  37.  
  38.  
  39.  
  40. //В файле "CirclesSummaryProps.cs":
  41.         public string CoordNumberXR
  42.         {
  43.             get
  44.             {
  45.                 return GetStringProp("CoordNumberXR");
  46.             }
  47.             set
  48.             {
  49.                 SetPropValue("CoordNumberXR", value);
  50.                 OnPropertyChanged(new PropertyChangedEventArgs("CoordNumberXR"));
  51.             }
  52.         }
  53.  

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
А что в этом сложного для новичка?
Сложно будет разобраться как там всё устроено и работает. Это не такие уж тривиальные вещи.