如何在WPF中为RichTextBox或AvalonEdit实现RuleLine(暗线)
实现编辑器每行RuleLine(暗线)的方案
一、使用AvalonEdit实现
AvalonEdit自带灵活的自定义渲染接口,很适合做这类编辑器样式定制:
- 自定义行背景渲染器
创建实现IBackgroundRenderer接口的类,专门绘制每行暗线:
using ICSharpCode.AvalonEdit.Rendering; using System.Windows.Media; public class RuleLineRenderer : IBackgroundRenderer { public KnownLayer Layer => KnownLayer.Background; public void Draw(TextView textView, DrawingContext drawingContext) { var pen = new Pen(Brushes.LightGray, 0.5); pen.Freeze(); foreach (var visualLine in textView.VisualLines) { var lineTop = visualLine.TextLine.GetLineBounds(0).Top; var lineY = textView.TextLinesToPixels(lineTop); var startPoint = new Point(textView.ActualWidth, lineY); var endPoint = new Point(0, lineY); drawingContext.DrawLine(pen, startPoint, endPoint); } } }
- 绑定到AvalonEdit控件
在窗口初始化或控件加载时,把渲染器添加到AvalonEdit的TextView中:
private void Window_Loaded(object sender, RoutedEventArgs e) { avalonEdit.TextArea.TextView.BackgroundRenderers.Add(new RuleLineRenderer()); }
这样每行底部会自动出现淡灰色暗线,且能跟随编辑器滚动、行高变化实时更新。
二、使用RichTextBox实现
RichTextBox需要通过装饰器(Adorner)实现跨行暗线绘制:
- 创建自定义Adorner类
using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Media; public class RuleLineAdorner : Adorner { private readonly RichTextBox _richTextBox; private readonly Pen _pen; public RuleLineAdorner(RichTextBox richTextBox) : base(richTextBox) { _richTextBox = richTextBox; _pen = new Pen(Brushes.LightGray, 0.5); _pen.Freeze(); _richTextBox.ScrollChanged += OnScrollChanged; } private void OnScrollChanged(object sender, ScrollChangedEventArgs e) { InvalidateVisual(); } protected override void OnRender(DrawingContext drawingContext) { base.OnRender(drawingContext); var document = _richTextBox.Document; if (document == null) return; var startPos = document.ContentStart; while (startPos != null) { if (startPos.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text) { var rect = startPos.GetCharacterRect(LogicalDirection.Forward); // 避开第一行顶部空白,只绘制行底部的线 if (rect.Y > _richTextBox.Padding.Top) { var lineY = rect.Bottom; var startPoint = new Point(_richTextBox.Padding.Left, lineY); var endPoint = new Point(_richTextBox.ActualWidth - _richTextBox.Padding.Right, lineY); drawingContext.DrawLine(_pen, startPoint, endPoint); } } startPos = startPos.GetNextContextPosition(LogicalDirection.Forward); } } }
- 添加装饰器到RichTextBox
在控件加载时,将装饰器添加到RichTextBox的AdornerLayer:
private void Window_Loaded(object sender, RoutedEventArgs e) { var adornerLayer = AdornerLayer.GetAdornerLayer(richTextBox); adornerLayer.Add(new RuleLineAdorner(richTextBox)); }
这个实现会监听滚动事件,确保滚动时暗线正确刷新,同时适配RichTextBox的内边距设置。
内容的提问来源于stack exchange,提问作者sodiseng
相关产品推荐
相关产品推荐

