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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:04:48