Сохранение введенных параметров команды для повторного использования

Автор Тема: Сохранение введенных параметров команды для повторного использования  (Прочитано 13273 раз)

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

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Проблема в другом: изменения этих параметров видят все открытые в данный момент чертежи. То есть они являются не локальными для каждого чертежа, а глобальными. Иначе говоря, изменяя параметры команды в одном чертеже и сохраняя их таким способом, в другом параллельно открытом чертеже, читаю только что измененные параметры.
Ну как выше уже ответили - использовать тогда вам XData

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

  • ADN Club
  • *****
  • Сообщений: 624
  • Карма: 158
    • ПГСу Бложик
Я немного дополню. Пространство модели - объект и к нему можно добавлять XData/

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

  • ADN OPEN
  • Сообщений: 47
  • Карма: 0
Благодарю всех за ответы. В общем, я решил остановиться пока на сохранении своих переменных средствами Visual Studio, как наиболее простом. Использование xData для таких целей вижу неудобным, поскольку объекты могут копироваться и удаляться, таким образом теряются прикрепленные данные. Сохранение пользовательских данных чертежей - код на будущее будет мне полезен, но для других задач. Сейчас не хочу выносить внутренние данные во вкладку, доступную для редактирования пользователем вне самой команды. Странно и неудобно, что нет возможности создавать свои значения по типу системных переменных, сохраняемых в чертеже.

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Использование xData для таких целей вижу неудобным, поскольку объекты могут копироваться и удаляться, таким образом теряются прикрепленные данные
Вам же сказали - вы можете хранить XData в самом чертеже. И пример выше дали. Эти данные никуда не денутся

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

  • ADN Club
  • *****
  • Сообщений: 624
  • Карма: 158
    • ПГСу Бложик
Использование xData для таких целей вижу неудобным, поскольку объекты могут копироваться и удаляться, таким образом теряются прикрепленные данные
Пространство модели - объект и к нему можно добавлять XData/
Вот как можно потерять пространство модели?

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Ну как я и сказал - открываете свойства проекта и идете на вкладку "Параметры". Её многие привыкли использовать для локализации (не лучший способ, ИМХО). Там ручками создаем параметры. При этом мы задаем тип данных и значение по умолчанию (которое Phil почему-то не увидел).
При этом VisualStudio создает специальный класс
Дальше уже в коде использовать эти параметры проще простого
Код - C# [Выбрать]
var isCurrent = Properties.Settings.Default.IsCurrent;
При задании новых значений нужно не забывать вызывать метод сохранения, так как само это не происходит
Код - C# [Выбрать]
Properties.Settings.Default.IsCurrent = true;
Properties.Settings.Default.Save();
Еще эти параметры удобно биндить на WPF окна, что сокращает количество кода в разы
Хм, как интересно! То ли раньше этот механизм по-другому работал, то ли я в нём в своё время не до конца разобрался. Спасибо!
Вот мой хелпер для записи в свойства чертежа
Я немного дополню. Пространство модели - объект и к нему можно добавлять XData/
Странно, что никто ещё не посоветовал использовать NamedObjectDictionary. Хотя, на мой взгляд, это самое оптимальное место хранения данных уровня чертежа.

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

  • ADN OPEN
  • Сообщений: 47
  • Карма: 0
Странно, что никто ещё не посоветовал использовать NamedObjectDictionary. Хотя, на мой взгляд, это самое оптимальное место хранения данных уровня чертежа.
А можно пример практической реализации? Я пробовал читать и записывать, но не разобрался как, к примеру, записать в словарь числовое значение double

Отмечено как Решение Phil 24-03-2018, 13:02:56

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737

Оффлайн avc

  • ADN Club
  • *****
  • Сообщений: 822
  • Карма: 166
    • Мои плагины к Автокаду
Странно, что никто ещё не посоветовал использовать NamedObjectDictionary
Почему же никто? Первый комментарий в теме:
Если надо сохранить в чертеж - я бы использовал словари и xRecord

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

  • ADN OPEN
  • Сообщений: 47
  • Карма: 0
Один из самых простых и наглядных: https://forums.autodesk.com/t5/net/save-some-variables-into-dwg-file-how-c/td-p/3617358
Ну и, классика: https://google.gik-team.com/?q=autocad+net+namedobjectsdictionary ;)
Обнаружилась некоторая проблема при использовании этого решения... Ниже приведен код.

Последовательность действий, иллюстрирующих проблему:
1. Команда SaveVar. Ввести число, отличное от числа по умолчанию (в начале это "5.555"). Скажем, "777"
2. Любая другая команда (к примеру Line).
3. Команда SaveVar. Ввести число, отличное от числа по умолчанию (теперь это "777"). Скажем, "888"
4. Вызвать команду Undo.
5. Команда ReadVar.

Результат выполнения последней команды будет "5.555", хотя должно бы быть "777"

Код - C# [Выбрать]
  1. using Autodesk.AutoCAD.Runtime;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.EditorInput;
  5.  
  6. public class MyCommands
  7. {
  8.  
  9.     public void WriteXrecord(Document doc, string dictName, string key, ResultBuffer resbuf)
  10.     {
  11.         Database db = doc.Database;
  12.         using (Transaction tr = db.TransactionManager.StartTransaction())
  13.         {
  14.             DBDictionary NOD =
  15.                 (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
  16.             DBDictionary dict;
  17.             if (NOD.Contains(dictName))
  18.             {
  19.                 dict = (DBDictionary)tr.GetObject(NOD.GetAt(dictName), OpenMode.ForWrite);
  20.             }
  21.             else
  22.             {
  23.                 dict = new DBDictionary();
  24.                 NOD.UpgradeOpen();
  25.                 NOD.SetAt(dictName, dict);
  26.                 tr.AddNewlyCreatedDBObject(dict, true);
  27.             }
  28.             Xrecord xRec = new Xrecord();
  29.             xRec.Data = resbuf;
  30.             dict.SetAt(key, xRec);
  31.             tr.AddNewlyCreatedDBObject(xRec, true);
  32.             tr.Commit();
  33.         }
  34.     }
  35.  
  36.     public ResultBuffer ReadXrecord(Document doc, string dictName, string key)
  37.     {
  38.         Database db = doc.Database;
  39.         using (Transaction tr = db.TransactionManager.StartTransaction())
  40.         {
  41.             DBDictionary NOD =
  42.                 (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
  43.             if (!NOD.Contains(dictName))
  44.                 return null;
  45.             DBDictionary dict = tr.GetObject(NOD.GetAt(dictName), OpenMode.ForRead) as DBDictionary;
  46.             if (dict == null || !dict.Contains(key))
  47.                 return null;
  48.             Xrecord xRec = tr.GetObject(dict.GetAt(key), OpenMode.ForRead) as Xrecord;
  49.             if (xRec == null)
  50.                 return null;
  51.             return xRec.Data;
  52.         }
  53.     }
  54.  
  55.     public void WriteDouble(Document doc, string acDictName, string acKey, double var)
  56.     {
  57.         ResultBuffer acResultBuffer = new ResultBuffer();
  58.         acResultBuffer.Add(new TypedValue((int)DxfCode.ExtendedDataReal, var));
  59.         WriteXrecord(doc, acDictName, acKey, acResultBuffer);
  60.  
  61.     }
  62.  
  63.     public double ReadXDouble(Document doc, string acDictName, string acKey, double acDefault)
  64.     {
  65.         ResultBuffer acResultBuffer = new ResultBuffer();
  66.         acResultBuffer = ReadXrecord(doc, acDictName, acKey);
  67.         if (acResultBuffer != null)
  68.             return (double)acResultBuffer.AsArray()[0].Value;
  69.         else return acDefault;
  70.     }
  71.  
  72.     [CommandMethod("savevar", CommandFlags.Modal)]
  73.     public void MyCommand1()
  74.     {
  75.         Document doc = Application.DocumentManager.MdiActiveDocument;
  76.         double var = ReadXDouble(doc, "dist", "key", 5.555);
  77.  
  78.         PromptDoubleOptions pdo = new PromptDoubleOptions("Введите число");
  79.         pdo.DefaultValue = var;
  80.         PromptDoubleResult pdr = doc.Editor.GetDouble(pdo);
  81.         if (pdr.Status != PromptStatus.OK) return;
  82.  
  83.         WriteDouble(doc, "dist_1", "key_1", pdr.Value);
  84.         Application.ShowAlertDialog("Переменная сохранена");
  85.     }
  86.  
  87.     [CommandMethod("readvar", CommandFlags.Modal)]
  88.     public void MyCommand2()
  89.     {
  90.         Document doc = Application.DocumentManager.MdiActiveDocument;
  91.         double var = ReadXDouble(doc, "dist_1", "key_1", 5.555);
  92.         Application.ShowAlertDialog("Сохраненное число = " + var);
  93.     }
  94. }

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

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

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

  • ADN OPEN
  • Сообщений: 47
  • Карма: 0
Почитай: http://adndevblog.typepad.com/autocad/2012/07/undo-removes-updated-dictionary-entry.html

Снимаю шляпу перед вашими знаниями и отзывчивостью! В соответствии с рекомендацией по ссылке скорректировал процедуру записи значения:

Код - C# [Выбрать]
  1.     public void WriteXrecord(Document doc, string dictName, string key, ResultBuffer resbuf)
  2.     {
  3.         Database db = doc.Database;
  4.         using (Transaction tr = db.TransactionManager.StartTransaction())
  5.         {
  6.             DBDictionary NOD = (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
  7.             DBDictionary dict;
  8.             if (NOD.Contains(dictName))
  9.             {
  10.                 dict = (DBDictionary)tr.GetObject(NOD.GetAt(dictName), OpenMode.ForWrite);
  11.             }
  12.             else
  13.             {
  14.                 dict = new DBDictionary();
  15.                 NOD.UpgradeOpen();
  16.                 NOD.SetAt(dictName, dict);
  17.                 tr.AddNewlyCreatedDBObject(dict, true);
  18.             }
  19.  
  20.             Xrecord xRec;
  21.             if (dict.Contains(key))
  22.             {
  23.                 // Дополнение к процедуре записи: если ключ существует, обновляем значение существующей xRec
  24.                 xRec = tr.GetObject(dict.GetAt(key), OpenMode.ForWrite) as Xrecord;
  25.                 xRec.Data = resbuf;
  26.             }
  27.             else
  28.             {
  29.                 xRec = new Xrecord();
  30.                 xRec.Data = resbuf;
  31.                 dict.SetAt(key, xRec);
  32.                 tr.AddNewlyCreatedDBObject(xRec, true);
  33.             }
  34.  
  35.             tr.Commit();
  36.         }
  37.     }