如何在WPF RichTextBox中高亮数字?现有实现出现随机字母高亮问题
解决WPF RichTextBox数字高亮时误选字母的问题
嘿,我帮你排查下这个问题~你遇到的字母被随机高亮的情况,核心原因是RichTextBox的GetPositionAtOffset方法和正则匹配的索引计数规则不一样!
问题根源
WPF的FlowDocument里,GetPositionAtOffset默认是按「文档符号」计数的——除了可见的文本,像段落标记、换行符甚至隐藏的格式符号都会被算成一个偏移单位。但你用正则匹配的是纯文本的索引,两者的计数完全不对齐,自然会导致选中的范围跑偏,把不该高亮的字母也包含进去了。
修正方案
我们需要写一个辅助方法,专门只统计纯文本的长度,来把正则匹配到的纯文本索引转换成正确的TextPointer位置。
第一步:添加纯文本偏移定位的辅助方法
private TextPointer GetTextPointerAtOffset(TextPointer start, int offset) { var current = start; int currentOffset = 0; while (current != null && currentOffset < offset) { // 只处理纯文本内容 if (current.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text) { int textLength = current.GetTextRunLength(LogicalDirection.Forward); // 如果当前文本段包含目标偏移,直接返回对应位置 if (currentOffset + textLength > offset) { return current.GetPositionAtOffset(offset - currentOffset); } currentOffset += textLength; } // 跳过非文本的符号(比如格式标记、段落符) current = current.GetNextContextPosition(LogicalDirection.Forward); } return current; }
第二步:修改你的TextChanged事件处理程序
把原来直接用GetPositionAtOffset的地方替换成这个辅助方法,确保定位准确:
private void DescriptionText_TextChanged(object sender, TextChangedEventArgs e) { var range = new TextRange(DescriptionText.Document.ContentStart, DescriptionText.Document.ContentEnd); var regex = new Regex("[0-9]+"); var num_ranges = new List<TextRange>(); foreach (Match match in regex.Matches(range.Text)) { // 使用辅助方法获取精准的文本位置 var start = GetTextPointerAtOffset(range.Start, match.Index); var end = GetTextPointerAtOffset(range.Start, match.Index + match.Length); // 确保位置有效再添加 if (start != null && end != null) { num_ranges.Add(new TextRange(start, end)); } } // 取消订阅避免递归触发修改事件 DescriptionText.TextChanged -= this.DescriptionText_TextChanged; // 重置所有文本为黑色 range.ClearAllProperties(); range.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Black)); // 给所有数字范围设置红色 foreach (var r in num_ranges) { r.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Red)); } // 重新订阅事件 DescriptionText.TextChanged += this.DescriptionText_TextChanged; }
额外提示
如果你的RichTextBox里有复杂格式(比如加粗、斜体),这个方法依然能正常工作,因为它只关注纯文本的偏移计数。要是遇到频繁输入时性能卡顿的情况,可以考虑加个DispatcherTimer延迟处理,避免每输入一个字符就立刻触发全量格式刷新。
内容的提问来源于stack exchange,提问作者ymbcKxSw
相关产品推荐
相关产品推荐

