Всем привет. Сделал переопределение ручек. Все нормально работает до того момента, пока я не перемещу одинаковые ручки двух объектов в одну точку. После этого ловится фатальная ошибка - либо просто при выборе этих объектов, либо при попытке перетащить эти ручки. С горем пополам при отладке я смог уловить одну ошибку (не ловится через try{}catch{}) -
System.ArgumentException: Элемент с тем же ключом уже был добавленУ меня создан свой GripData в котором есть ссылка на ObjectId объекта. Так же создал энумератор с "именами" ручек вместо использования индекса:
public enum BreakLineGripName
{
StartGrip,
MiddleGrip,
EndGrip
}
GripData выглядит примерно так (убрал toolTip'ы):
public class BreakLineGrip : MPCOGrips.MPCOGripData
{
// Ссылка на ObjectId блока
public ObjectId BlkRef { get; set; }
// Экземпляр класса, связанный с этим блоком
public BreakLine breakLine { get; set; }
// Имя ручки
public BreakLineGripName GripName { get; set; }
// Временное значение первой ручки
private Point3d _startGripTmp;
// временное значение последней ручки
private Point3d _endGripTmp;
public override void OnGripStatusChanged(ObjectId entityId, Status newStatus)
{
try
{
// Запоминаем начальные значения
if (newStatus == Status.GripStart)
{
if (GripName == BreakLineGripName.StartGrip)
_startGripTmp = GripPoint;
if (GripName == BreakLineGripName.EndGrip)
_endGripTmp = GripPoint;
if (GripName == BreakLineGripName.MiddleGrip)
{
_startGripTmp = breakLine.StartGrip;
_endGripTmp = breakLine.EndGrip;
}
}
// Сохраняем данные в расширенные данные примитива
if (newStatus == Status.GripEnd)
{
using (var tr = AcadHelpers.Database.TransactionManager.StartTransaction())
{
var blkRef = tr.GetObject(breakLine.BlockId, OpenMode.ForWrite);
using (var resBuf = breakLine.GetParametersForXData())
{
blkRef.XData = resBuf;
}
tr.Commit();
}
}
// При отмене перемещения возвращаем временные значения
if (newStatus == Status.GripAbort)
{
if (_startGripTmp != null & GripName == BreakLineGripName.StartGrip)
breakLine.EndPoint = GripPoint;
if (GripName == BreakLineGripName.MiddleGrip & _startGripTmp != null & _endGripTmp != null)
{
breakLine.InsertionPoint = _startGripTmp;
breakLine.EndPoint = _endGripTmp;
}
}
base.OnGripStatusChanged(entityId, newStatus);
}
catch (Exception exception)
{
MpExWin.Show(exception);
}
}
}
При работе метода GetGripPoints я получаю ручки и добавляю их в коллекцию
if (IsApplicable(entity))
{
// Удаляем стандартную ручку позиции блока (точки вставки)
GripData toRemove = null;
foreach (GripData gd in grips)
{
if (gd.GripPoint == blkRef.Position)
{
toRemove = gd;
break;
}
}
if (toRemove != null) grips.Remove(toRemove);
// Получаем ручки СПДС объекта
var breakLine = BreakLineXDataHelper.GetBreakLineFromEntity(entity);
if (breakLine != null)
{
// add start grip
var gp = new BreakLineGrip
{
BlkRef = entity.ObjectId,
breakLine = breakLine,
GripName = BreakLineGripName.StartGrip,
GripPoint = breakLine.StartGrip
};
grips.Add(gp);
// add middle grip
gp = new BreakLineGrip
{
BlkRef = entity.ObjectId,
breakLine = breakLine,
GripName = BreakLineGripName.MiddleGrip,
GripPoint = breakLine.MiddleGrip
};
grips.Add(gp);
// add end grip
gp = new BreakLineGrip
{
BlkRef = entity.ObjectId,
breakLine = breakLine,
GripName = BreakLineGripName.EndGrip,
GripPoint = breakLine.EndGrip
};
grips.Add(gp);
}
}
В методе MoveGripPointsAt я обновляю уже связанный с ручкой объект:
public override void MoveGripPointsAt(Autodesk.AutoCAD.DatabaseServices.Entity entity, GripDataCollection grips, Vector3d offset, MoveGripPointsFlags bitFlags)
{
try
{
foreach (GripData gripData in grips)
{
var gripPoint = gripData as BreakLineGrip;
if (gripPoint != null)
{
if (gripPoint.GripName == BreakLineGripName.StartGrip)
{
((BlockReference)entity).Position = gripPoint.GripPoint + offset;
gripPoint.breakLine.InsertionPoint = gripPoint.GripPoint + offset;
}
if (gripPoint.GripName == BreakLineGripName.MiddleGrip)
{
var lenghtVector = (gripPoint.breakLine.InsertionPoint - gripPoint.breakLine.EndPoint) / 2;
((BlockReference)entity).Position = gripPoint.GripPoint + offset + lenghtVector;
gripPoint.breakLine.InsertionPoint = gripPoint.GripPoint + offset + lenghtVector;
gripPoint.breakLine.EndPoint = gripPoint.GripPoint + offset - lenghtVector;
}
if (gripPoint.GripName == BreakLineGripName.EndGrip)
{
gripPoint.breakLine.EndPoint = gripPoint.GripPoint + offset;
}
gripPoint.breakLine.UpdateEntities();
gripPoint.breakLine.BlockRecord.UpdateAnonymousBlocks();
}
else base.MoveGripPointsAt(entity, grips, offset, bitFlags);
}
}
catch (Exception exception)
{
MpExWin.Show(exception);
}
}
Разве при этом в коллекции GripDataCollection grips мои ручки не получаются уникальными? Описанный вариант работает кроме только одного случая - как у же говорил - если две ручки двух объектов не переместить в одну точку