Я использую AvalonEdit и хочу, чтобы пользователь всегда мог видеть, на какой строке находится каретка, даже когда редактор не имеет фокуса. С этой целью я нашел и адаптировал некоторый код, который использует BackgroundRenderer для выделения фона текущей строки.
К сожалению, если я изменю CaretOffset, когда редактор не сфокусирован, мой фоновый прямоугольник останется на той строке, которая была текущей, когда редактор потерял фокус. Он не синхронизируется с новой текущей строкой, пока редактор снова не сфокусируется.
Я разобрался почему это происходит (просто не как это исправить). Согласно комментариям к документу для IBackgroundRenderer, «Фоновый рендер будет рисовать, только если их связанный известный слой выберет их рисование. Например, фоновые рендеры в слое каретки будут невидимы, когда каретка скрыта». Мой фоновый рендерер живет на KnownLayer.Caret, так что да, я понимаю, почему он не обновляется, когда редактор не сфокусирован - это потому, что каретка тоже скрыта. (Учитывая это, я на самом деле удивлен, что мой прямоугольник остается видимым.)
Я попытался явно вызвать textEditor.TextArea.TextView.InvalidateLayer (KnownLayer.Caret) сразу после установки CaretOffset, но это не дало никакого эффекта - я предполагаю, что вызов был проигнорирован, потому что курсор был скрыт.
Каков наилучший способ принудительно обновить подсветку текущей строки, даже если редактор не имеет фокуса?
Вот код для моего класса. Я, конечно, открыт, чтобы выбросить это и использовать другой подход, если есть лучший способ сделать это.
public class HighlightCurrentLineBackgroundRenderer : IBackgroundRenderer
{
private TextEditor _editor;
public HighlightCurrentLineBackgroundRenderer(TextEditor editor)
{
_editor = editor;
}
public KnownLayer Layer
{
get { return KnownLayer.Caret; }
}
public void Draw(TextView textView, DrawingContext drawingContext)
{
if (_editor.Document == null)
return;
textView.EnsureVisualLines();
var currentLine = _editor.Document.GetLineByOffset(_editor.CaretOffset);
foreach (var rect in BackgroundGeometryBuilder.GetRectsForSegment(textView, currentLine))
{
drawingContext.DrawRectangle(
new SolidColorBrush(Color.FromArgb(0x40, 0, 0, 0xFF)), null,
new Rect(rect.Location, new Size(textView.ActualWidth - 32, rect.Height)));
}
}
}
Затем в конструкторе UserControl я добавляю средство визуализации в редактор:
textEditor.TextArea.TextView.BackgroundRenderers.Add(
new HighlightCurrentLineBackgroundRenderer(textEditor));