Ручка удаления вершины: ошибка в GetGripPoints() после удаления

Автор Тема: Ручка удаления вершины: ошибка в GetGripPoints() после удаления  (Прочитано 3216 раз)

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

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Всем привет. Пытаюсь сделать ручку удаления вершины в моем объекте (внутри полилиния).
В GripData в методе OnGripStatusChanged удаляю вершину примерно так:
Код - C# [Выбрать]
  1. public override void OnGripStatusChanged(ObjectId entityId, Status newStatus)
  2. {
  3.     try
  4.     {
  5.         if (newStatus == Status.GripStart)
  6.         {
  7.             if (GripIndex != 0)
  8.             {
  9.                 GroundLine.MiddlePoints.RemoveAt(GripIndex - 1);
  10.             }
  11.  
  12.             GroundLine.UpdateEntities();
  13.             GroundLine.BlockRecord.UpdateAnonymousBlocks();
  14.             using (var tr = AcadHelpers.Database.TransactionManager.StartOpenCloseTransaction())
  15.             {
  16.                 var blkRef = tr.GetObject(GroundLine.BlockId, OpenMode.ForWrite);
  17.                 using (var resBuf = GroundLine.GetParametersForXData())
  18.                 {
  19.                     blkRef.XData = resBuf;
  20.                 }
  21.  
  22.                 tr.Commit();
  23.             }
  24.  
  25.             GroundLine.Dispose();
  26.         }
  27.     }
  28.     catch (Exception exception)
  29.     {
  30.         ExceptionBox.Show(exception);
  31.     }
  32. }
При клике по ручке автокад падает с фатальной ошибкой.
При отладке проверил - все работает на ура - вершина удаляется и мой объект перерисовывается как надо. Затем сразу срабатывает метод GetGripPoints() в котором вроде все проходит нормально - ручки добавляются в коллекцию ручек и когда я дохожу до конца метода, то появляется ошибка:
Цитировать
Приложение не поддерживает оперативную (JIT)
отладку. Подробная информацию приводится в конце данного сообщения.

************** Текст исключения **************
System.ArgumentException: Элемент с тем же ключом уже был добавлен.
   в System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   в System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   в AcMgGripOverrule.getGripPoints(AcMgGripOverrule* , AcDbEntity* pSubject, AcArray<AcDbGripData \*\,AcArrayMemCopyReallocator<AcDbGripData \*> >* grips, Double curViewUnitSize, Int32 gripSize, AcGeVector3d* curViewDir, Int32 bitflags)
Посмотрел GripDataCollection - она не использует Dictionary. Тогда вопрос - где происходит ошибка?

Отмечено как Решение Александр Пекшев aka Modis 11-11-2018, 00:32:48

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Что-то подобное у тебя уже было: http://adn-cis.org/forum/index.php?topic=7814.0
И не только у тебя: http://adn-cis.org/forum/index.php?topic=8211.0
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Что-то подобное у тебя уже было: http://adn-cis.org/forum/index.php?topic=7814.0
Да, было и решилось заменой транзакции на SubTransaction. Сейчас я и делаю по той-же самой аналогии и проблема в чем-то другом

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

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

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Александр Пекшев aka Modis,
Вторую ссылку посмотри.
О! Отличное решение Дмитрия! Жаль, что я пропустил эту тему и не видел его. Проблему с фатальной ошибкой решило.
Но появилась другая проблема, которая как-раз и объясняет причину первой проблемы - мой код удалил вершину объекта, но продолжил работу метод MoveGripPointsAt():



Как заставить GripOverrule этого не делать?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Но появилась другая проблема, которая как-раз и объясняет причину первой проблемы - мой код удалил вершину объекта, но продолжил работу метод MoveGripPointsAt():
Ты пытаешься использовать ручки не по их прямому назначению. И пожинаешь результат...
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

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

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

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

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

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Нашёл решение:
Вместо переопределения метода OnGripStatusChanged в GripData (как я показал в топике вопроса) нужно сделать так:
Код - C# [Выбрать]
  1. public override ReturnValue OnHotGrip(ObjectId entityId, Context contextFlags)
  2. {
  3.     using (GroundLine)
  4.     {
  5.         if (GripIndex != 0)
  6.         {
  7.             GroundLine.MiddlePoints.RemoveAt(GripIndex - 1);
  8.         }
  9.  
  10.         GroundLine.UpdateEntities();
  11.         GroundLine.BlockRecord.UpdateAnonymousBlocks();
  12.         using (var tr = AcadHelpers.Database.TransactionManager.StartOpenCloseTransaction())
  13.         {
  14.             var blkRef = tr.GetObject(GroundLine.BlockId, OpenMode.ForWrite);
  15.             using (var resBuf = GroundLine.GetParametersForXData())
  16.             {
  17.                 blkRef.XData = resBuf;
  18.             }
  19.  
  20.             tr.Commit();
  21.         }
  22.     }
  23.  
  24.     return ReturnValue.GetNewGripPoints;
  25. }

При этом исчезает и ошибка "Элемент с тем же ключом уже был добавлен" и лайфхак из ссылки с решением Дмитрия не нужен )