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

WPF RichTextBox指定行插入文本如何保留原有颜色等格式

WPF RichTextBox指定行插入文本且保留原有格式方案

原有方案丢失格式的核心原因是调用Document.Blocks.Clear()会删除所有带格式属性的段落、行内元素,后续重新写入纯文本时只会应用控件默认格式,之前手动设置的字体、颜色等属性自然全部丢失。不需要维护独立的纯文本行列表做全量重写,直接操作RichTextBox的文档块结构做定点插入即可,全程不会改动已有内容的任何格式。

核心实现逻辑

WPF RichTextBox的文档内容以Block元素为单位存储,常规输入下每一个Paragraph块对应一行内容,Document.Blocks集合本身支持按索引插入元素,直接在目标位置插入新段落即可,原有块会自动后移,格式完整保留。

实现代码

先写两个通用扩展方法,覆盖行插入、总行数获取能力:

using System.Linq;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;

public static class RichTextBoxExtensions
{
    /// <summary>
    /// 在指定行索引位置插入新行,不改动原有内容的格式
    /// </summary>
    /// <param name="lineIndex">插入位置的行索引,从0开始</param>
    /// <param name="text">新行文本内容</param>
    /// <param name="foreground">新行字体颜色,默认用控件默认值</param>
    /// <param name="fontSize">新行字号,默认12号</param>
    public static void InsertLineAt(this RichTextBox richTextBox, int lineIndex, string text, Brush foreground = null, double fontSize = 12)
    {
        int totalLines = richTextBox.GetLineCount();
        // 边界校正:索引小于0插在最开头,大于当前总行数插在最末尾
        int insertPos = lineIndex < 0 ? 0 : lineIndex > totalLines ? totalLines : lineIndex;

        // 构建带格式的新段落
        Paragraph newLine = new Paragraph();
        Run textRun = new Run(text);
        if (foreground != null)
        {
            textRun.Foreground = foreground;
        }
        textRun.FontSize = fontSize;
        newLine.Inlines.Add(textRun);

        // 定点插入新段落,原有内容完全不受影响
        if (insertPos == totalLines)
        {
            richTextBox.Document.Blocks.Add(newLine);
        }
        else
        {
            Block targetBlock = richTextBox.Document.Blocks.ElementAt(insertPos);
            richTextBox.Document.Blocks.InsertBefore(targetBlock, newLine);
        }
    }

    /// <summary>
    /// 获取当前RichTextBox的总行数(按段落计数)
    /// </summary>
    public static int GetLineCount(this RichTextBox richTextBox)
    {
        return richTextBox.Document.Blocks.OfType<Paragraph>().Count();
    }
}

原有业务逻辑替换

把之前全清重写的逻辑全部删掉,换成直接调用插入方法,代码量更短,也不会丢格式:

// 计算插入位置,对应原有逻辑的插入到倒数第二行的需求
int insertIndex = richTextBox.GetLineCount() - 1;
// 直接插入红色字体的新行,之前所有行的颜色、字体格式完全保留
richTextBox.InsertLineAt(insertIndex, value.ToString("X4"), foreground: Brushes.Red);
// 滚动到控件末尾
richTextBox.ScrollToEnd();

特殊场景说明

  • 如果你的内容中存在手动输入的换行符(单个段落内拆分为多个视觉行),上述按段落计数的行索引和视觉行可能不匹配,只需要通过TextPointer.GetLineStartPosition方法遍历计算视觉行的对应位置即可,常规按行输出日志、插入内容的场景下,段落和视觉行是一一对应的,不需要额外处理。
  • 所有针对内容的增删改操作都直接对Document.Blocks或对应段落的Inlines集合做定点操作,不要用全量清空重写的方式,从根源上避免格式丢失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 14:54:19