【问题标题】:AvalonEdit: highlight current line even when not focusedAvalonEdit:即使没有聚焦也可以突出显示当前行
【发布时间】:2011-07-01 15:51:29
【问题描述】:

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

不幸的是,如果我在编辑器没有获得焦点的情况下更改 CaretOffset,我的背景矩形会停留在编辑器失去焦点时的当前行上。在编辑器再次获得焦点之前,它不会同步到新的当前行。

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

我尝试在设置 CaretOffset 后立即显式调用 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));

【问题讨论】:

  • 刚用过,效果很赞。此外,我稍微修改了它以考虑水平滚动,最后一行是: new Rect(new Point(rect.Location.X + textView.ScrollOffset.X, rect.Location.Y), new Size(textView .ActualWidth, rect.Height)));
  • 在每个绘制周期中创建 SolidColorBrush 效率不高。在构造函数中创建一次,冻结它并在 Draw 方法中引用。

标签: c# avalonedit


【解决方案1】:

这就是我最终完成这项工作的方式。

首先,我将 HighlightCurrentLineBackgroundRenderer 的 Layer 属性更改为返回 KnownLayer.Background。即使编辑器没有焦点,背景层也是可见的,这样就解决了原来的问题。

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-20
    • 1970-01-01
    • 2013-08-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多