C# AvalonEdit:即使在未聚焦时也高亮显示当前行

C# AvalonEdit:即使在未聚焦时也高亮显示当前行,c#,avalonedit,C#,Avalonedit,我使用的是AvalonEdit,我希望用户始终能够看到插入符号在哪一行,即使编辑器没有焦点。为此,我找到并修改了一些使用BackgroundRenderer突出显示当前行背景的代码 不幸的是,如果我在编辑器未聚焦时更改CareTofset,我的背景矩形将保持不变,位于编辑器失去焦点时的当前行上。直到编辑器再次获得焦点,它才会同步到新的当前行 我明白了为什么会发生这种情况(只是不知道如何解决)。根据IBackgroundRenderer的文档注释,“仅当背景渲染器的关联已知层选择绘制它们时,背景渲

我使用的是AvalonEdit,我希望用户始终能够看到插入符号在哪一行,即使编辑器没有焦点。为此,我找到并修改了一些使用BackgroundRenderer突出显示当前行背景的代码

不幸的是,如果我在编辑器未聚焦时更改CareTofset,我的背景矩形将保持不变,位于编辑器失去焦点时的当前行上。直到编辑器再次获得焦点,它才会同步到新的当前行

我明白了为什么会发生这种情况(只是不知道如何解决)。根据IBackgroundRenderer的文档注释,“仅当背景渲染器的关联已知层选择绘制它们时,背景渲染器才会绘制。例如,当插入符号被隐藏时,插入符号层中的背景渲染器将不可见。”我的背景渲染器位于KnownLayer.caret上,所以是,我明白为什么当编辑器没有聚焦时它没有更新——因为插入符号也是隐藏的。(考虑到这一点,我很惊讶我的矩形仍然可见。)

我尝试在设置CareTofSet后立即显式调用textEditor.TextArea.TextView.InvalidateLayer(KnownLayer.Caret),但没有效果——我猜该调用被忽略,因为插入符号是隐藏的

即使编辑器没有焦点,强制更新当前行高亮显示的最佳方法是什么?


这是我们班的代码。如果有更好的方法的话,我当然愿意把它扔掉,换一种方法

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));

下面是我如何完成这项工作的

首先,我更改了HighlightCurrentLineBackgroundRenderer的层属性以返回KnownLayer.Background。即使编辑器没有焦点,背景层也可见,因此解决了原始问题

然而,它引入了一个新的问题:背景层只在某些条件下被重绘,而“插入符号移动”不是这些条件之一——所以现在高光根本不移动!(好吧,确实如此——例如,当你滚动或选择文本时。但这不是你想要的行为。)但这很容易解决;我只需要在插入符号移动时手动使背景层无效:

textEditor.TextArea.Caret.PositionChanged += (sender, e) =>
    textEditor.TextArea.TextView.InvalidateLayer(KnownLayer.Background);

这就是它的全部——现在,即使编辑器没有聚焦,高亮显示也会更新。

刚刚使用了它,喜欢它的效果。另外,为了考虑水平滚动,我稍微修改了它,最后一行是:new Rect(new Point(Rect.Location.X+textView.ScrollOffset.X,Rect.Location.Y),new Size(textView.ActualWidth,Rect.Height));在每个绘制周期中创建SolidColorBrush是无效的。在构造函数中创建一次,冻结它并在Draw方法中引用。