Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: Александр Пекшев aka Modis от 10-11-2018, 23:42:06

Название: Ручка удаления вершины: ошибка в GetGripPoints() после удаления
Отправлено: Александр Пекшев aka Modis от 10-11-2018, 23:42:06
Всем привет. Пытаюсь сделать ручку удаления вершины в моем объекте (внутри полилиния).
В 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. Тогда вопрос - где происходит ошибка?
Название: Re: Ручка удаления вершины: ошибка в GetGripPoints() после удаления
Отправлено: Александр Ривилис от 11-11-2018, 00:00:50
Что-то подобное у тебя уже было: http://adn-cis.org/forum/index.php?topic=7814.0
И не только у тебя: http://adn-cis.org/forum/index.php?topic=8211.0
Название: Re: Ручка удаления вершины: ошибка в GetGripPoints() после удаления
Отправлено: Александр Пекшев aka Modis от 11-11-2018, 00:07:13
Что-то подобное у тебя уже было: http://adn-cis.org/forum/index.php?topic=7814.0
Да, было и решилось заменой транзакции на SubTransaction. Сейчас я и делаю по той-же самой аналогии и проблема в чем-то другом
Название: Re: Ручка удаления вершины: ошибка в GetGripPoints() после удаления
Отправлено: Александр Ривилис от 11-11-2018, 00:10:58
Александр Пекшев aka Modis,
Вторую ссылку посмотри.
Название: Re: Ручка удаления вершины: ошибка в GetGripPoints() после удаления
Отправлено: Александр Пекшев aka Modis от 11-11-2018, 00:32:25
Александр Пекшев aka Modis,
Вторую ссылку посмотри.
О! Отличное решение Дмитрия! Жаль, что я пропустил эту тему и не видел его. Проблему с фатальной ошибкой решило.
Но появилась другая проблема, которая как-раз и объясняет причину первой проблемы - мой код удалил вершину объекта, но продолжил работу метод MoveGripPointsAt():

(https://i.postimg.cc/pyZrYjg3/grip.gif) (https://postimg.cc/pyZrYjg3)

Как заставить GripOverrule этого не делать?
Название: Re: Ручка удаления вершины: ошибка в GetGripPoints() после удаления
Отправлено: Александр Ривилис от 11-11-2018, 00:51:06
Но появилась другая проблема, которая как-раз и объясняет причину первой проблемы - мой код удалил вершину объекта, но продолжил работу метод MoveGripPointsAt():
Ты пытаешься использовать ручки не по их прямому назначению. И пожинаешь результат...
Название: Re: Ручка удаления вершины: ошибка в GetGripPoints() после удаления
Отправлено: Александр Пекшев aka Modis от 11-11-2018, 00:52:47
Но появилась другая проблема, которая как-раз и объясняет причину первой проблемы - мой код удалил вершину объекта, но продолжил работу метод MoveGripPointsAt():
Ты пытаешься использовать ручки не по их прямому назначению. И пожинаешь результат...
Ну я вроде не первый так делаю) У других-же как-то получилось! Или есть еще какие-то виды ручек о которых я не знаю?
Название: Re: Ручка удаления вершины: ошибка в GetGripPoints() после удаления
Отправлено: Александр Ривилис от 11-11-2018, 01:00:11
В AutoCAD'е ручка служит или для перемещения или для появления контекстного меню.
Название: Re: Ручка удаления вершины: ошибка в GetGripPoints() после удаления
Отправлено: Александр Пекшев aka Modis от 11-11-2018, 01:04:26
Нашёл решение:
Вместо переопределения метода 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. }

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