Текстовые украшения в VS2010: ИНОГДА отображаются в неправильных позициях

Ты моя единственная надежда. Я искал везде и просто не могу найти ничего, что могло бы помочь мне с этим.

Я сделал простой плагин для маркировки кода для Visual Studio (2010). Он просто находит некоторые части кода, которые нужно выделить (от Regex), создает Spans из найденных совпадений, а затем создает для них украшения Rectangle (на заднем плане текста), которые прокручивают текст. Все это делается в реализации события view.LayoutChanged. Работает нормально... но... НЕ КАЖДЫЙ РАЗ! Иногда маркеры перемещаются на различные расстояния (в основном вверх или вниз), а затем просто сохраняют эти неправильные позиции во время прокрутки текста. Понятия не имею почему и КОГДА это происходит. Мне удалось обнаружить только эти несколько вещей:

  • Вы можете воспроизвести эту ошибку (переместить некоторые маркеры из их правильных положений), перетаскивая вертикальную полосу прокрутки окна редактора кода очень быстро и агрессивно вверх и вниз (но иногда это также фиксирует позиции...)
  • Вы не можете зафиксировать положение маркера, отредактировав строку, на которой он находится (или даже помеченный текст)
  • Вы можете исправить положение маркера, удалив и восстановив конечную "}" блока кода, в котором размещен отмеченный код (что приводит к переформатированию всего блока кода)
  • view.ViewportTop является отрицательным, когда позиции вычисляются неправильно (view является классом WpfTextView), а геометрия "g" (см. ниже) тоже получает отрицательную оценку Bounds.Top. (Вы можете проверить это, прикрепив одну VS к другой и установив точку останова)

Вот фрагмент моего кода, который вычисляет позиции и создает маркеры (событие LayoutChanged):

Geometry g = textViewLines.GetMarkerGeometry(span);
if (g != null)
{
    GeometryDrawing drawing = new GeometryDrawing(_brush, _pen, g);
    drawing.Freeze();

    DrawingImage drawingImage = new DrawingImage(drawing);
    drawingImage.Freeze();

    Image image = new Image();
    image.Source = drawingImage;

    //Align the image with the top of the bounds of the text geometry
    Canvas.SetLeft(image, g.Bounds.Left);
    Canvas.SetTop(image, g.Bounds.Top);

    //_layer.AddAdornment(AdornmentPositioningBehavior.TextRelative, span, null, image, null);

    Rect rect = new Rect(g.Bounds.Location, g.Bounds.Size);
    Rectangle marker = new Rectangle();
    marker.Margin = new Thickness(rect.X - 3, rect.Y - 2, 0, 0);
    marker.Width = rect.Width + 6; marker.Height = rect.Height + 4;
    marker.Fill = new SolidColorBrush(mark);
    marker.RadiusX = marker.RadiusY = 5;
    marker.Stroke = new SolidColorBrush(color);
    _layer.AddAdornment(AdornmentPositioningBehavior.TextRelative, span, null, marker, null);
}

Это в основном пример MSDN для создания украшений, я не делаю здесь никакой магии.

Пожалуйста помоги!

2 ответа

Я только что провел целый день по аналогичной проблеме.

Есть много недокументированных угловых случаев, кроме проблемы перемещения пролета. Что еще хуже, кажется, что проверенное решение имеет тенденцию ломаться в никогда не версии VS (особенно, начиная с Roslyn и VS2015). Моим любимым было следующее: украшения иногда удалялись, если вы нажимали несколько раз клавишу ввода внутри многострочного комментария. Веселое!

Итак, единственный рабочий подход заключается в следующем: не пытайтесь перехитрить VS-редактор, он все равно вас обманет.

Вместо этого позаимствуйте код у Розлина AdornmentManager<T>, Он содержит много хаков, которые мне пришлось заново изобрести, и даже больше, о которых я даже не подозревал, но это работает. Все, что вам нужно сделать, это заменить код ниже

// add the visual to the adornment layer.

с твоим (часть - хороший кандидат на рефакторинг в переопределяемый метод).

PS Я знаю, что я немного опоздал:) Надеюсь, это сэкономит время другой бедной душе.

У меня такая же проблема. Если вы используете

_layer.AddAdornment(AdornmentPositioningBehavior.TextRelative,...);

больше, чем когда вы должны вставить

Canvas.SetLeft(image, g.Bounds.Left);
Canvas.SetTop(image, g.Bounds.Top);

каждый раз раньше.

Другие вопросы по тегам