You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用IBackgroundRenderer实现AvalonEdit选中词全高亮?

AvalonEdit实现选中单词全文档高亮(解决默认高亮冲突问题)

作为C#新手,在开发嵌入AvalonEdit的代码编辑器时,需要实现选中单词全文档高亮功能。最初使用DocumentColorizingTransformer实现,但出现了与默认语法高亮冲突、视觉显示有瑕疵的问题。

了解到可以通过IBackgroundRenderer类来实现该功能,但现有资料仅提供Draw方法的结构框架,缺少完整实现细节,尤其是不清楚如何传递需要高亮的匹配词。最终自行解决问题,以下是完整可运行代码:

1. 高亮渲染器核心实现

using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Rendering;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;

namespace SVGRecolorTool {

    public class SearchResult : TextSegment {
        /// <summary>搜索结果对应的正则匹配项</summary>
        public Match Match { get; }

        /// <summary>从匹配项构造搜索结果</summary>
        public SearchResult(Match match) {
            this.StartOffset = match.Index;
            this.Length = match.Length;
            this.Match = match;
        }
    }

    public class HighlightSelectedWordBackgroundRenderer : IBackgroundRenderer {

        private TextEditor _editor;

        TextSegmentCollection<SearchResult> currentResults = new TextSegmentCollection<SearchResult>();

        public HighlightSelectedWordBackgroundRenderer(TextEditor editor) {
            _editor = editor;
            Background = new SolidColorBrush(Color.FromArgb(90, 255, 255, 255));
            Background.Freeze();
        }

        public KnownLayer Layer {
            get { return KnownLayer.Caret; }
        }

        public void Draw(TextView textView, DrawingContext drawingContext) {

            if (!textView.VisualLinesValid)
                return;

            var visualLines = textView.VisualLines;
            if (visualLines.Count == 0)
                return;

            int viewStart = visualLines.First().FirstDocumentLine.Offset;
            int viewEnd = visualLines.Last().LastDocumentLine.EndOffset;


            foreach (TextSegment result in currentResults.FindOverlappingSegments(viewStart, viewEnd - viewStart)) {
                BackgroundGeometryBuilder geoBuilder = new BackgroundGeometryBuilder();
                geoBuilder.AlignToWholePixels = true;
                geoBuilder.CornerRadius = 0;
                geoBuilder.AddSegment(textView, result);
                Geometry geometry = geoBuilder.CreateGeometry();
                if (geometry != null) {
                    drawingContext.DrawGeometry(Background, null, geometry);
                }
            }
        }

        public TextSegmentCollection<SearchResult> CurrentResults {
            get { return currentResults; }
        }

        public Brush Background { get; set; }
    }
}

2. 初始化渲染器

// 初始化高亮渲染器并绑定到编辑器
_renderer = new HighlightSelectedWordBackgroundRenderer(txtSvgSource);
txtSvgSource.TextArea.TextView.BackgroundRenderers.Add(_renderer);
// 监听选择变更事件触发高亮
txtSvgSource.TextArea.SelectionChanged += HighlightSelection;

3. 选择变更处理逻辑

private void HighlightSelection(object sender, EventArgs e) {

    _renderer.CurrentResults.Clear();

    // 仅处理长度大于2的选中文本,避免误触发
    if(txtSvgSource.SelectedText.Length > 2) {
        // 使用单词边界正则,确保匹配完整单词而非子串
        string pattern = @"\b" + txtSvgSource.SelectedText + @"\b";
        Regex rg = new Regex(pattern);
        MatchCollection matchedSelections = rg.Matches(txtSvgSource.Text);

        // 匹配数大于1时添加高亮项
        if (matchedSelections.Count > 1) {
            foreach (Match result in matchedSelections) {
                _renderer.CurrentResults.Add(new SearchResult(result));
            }
        } else {
            _renderer.CurrentResults.Clear();
        }

    } else {
        _renderer.CurrentResults.Clear();
    }     

    // 刷新高亮层,确保视觉更新
    txtSvgSource.TextArea.TextView.InvalidateLayer(KnownLayer.Selection);
}

内容的提问来源于stack exchange,提问作者fmotion1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 07:27:12