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

WPF MVVM项目RichTextBox非均质选中文本应用下划线/删除线偏移求助

问题根因

你遇到的格式偏移问题核心是4个逻辑错误导致的:

  • TextPointer偏移失效:循环中每次给单个字符应用格式时,RichTextBox会自动拆分原有Run节点,文档逻辑结构发生变化,GetPositionAtOffset(1)无法正确指向原选区内的下一个字符,遍历越靠后偏移量越大。
  • 状态判断逻辑不合理:仅取选中区域第一个字符的装饰线状态作为整个选区的切换依据,不符合常规富文本编辑器交互逻辑,也容易出现状态判断错误。
  • 异常捕获逻辑不规范:Selection.GetPropertyValue在选中内容格式混合时会返回DependencyProperty.UnsetValue,本身不会抛出异常,你当前的异常是强行给TextDecorationCollectionAdd空值触发的,用异常控制业务流程本身就属于不规范写法。
  • 附加错误:NewParagraphWhenSelectionIsEmpty方法中,FontWeight的判断错误用了btnItalics.IsChecked,应该改为btnBold.IsChecked,会导致空选时加粗和斜体状态串扰。

修复方案

不用自己逐字符遍历,直接通过属性值判断即可实现需求,修复后的下划线按钮点击逻辑如下:

private void btnUnderline_Click(object sender, RoutedEventArgs e)
{
    bool isButtonChecked = (sender as ToggleButton).IsChecked ?? false;
    if (contentRichTextBox.Selection.IsEmpty)
    {
        NewParagraphWhenSelectionIsEmpty();
        return;
    }

    var selection = contentRichTextBox.Selection;
    object decorationValue = selection.GetPropertyValue(Inline.TextDecorationsProperty);
    
    TextDecorationCollection newDecorations;
    // 格式混合状态,直接按按钮状态设置
    if (decorationValue == DependencyProperty.UnsetValue)
    {
        newDecorations = new TextDecorationCollection();
        if (isButtonChecked)
        {
            newDecorations.Add(TextDecorations.Underline);
        }
    }
    else
    {
        // 格式统一状态,切换下划线属性
        var existingDecorations = decorationValue as TextDecorationCollection ?? new TextDecorationCollection();
        newDecorations = new TextDecorationCollection(existingDecorations);
        if (isButtonChecked)
        {
            if (!newDecorations.Contains(TextDecorations.Underline[0]))
                newDecorations.Add(TextDecorations.Underline);
        }
        else
        {
            newDecorations.TryRemove(TextDecorations.Underline, out newDecorations);
        }
    }
    selection.ApplyPropertyValue(Inline.TextDecorationsProperty, newDecorations);
}

删除线按钮逻辑和上面完全一致,只需要把所有Underline替换为Strikethrough即可。

另外修复NewParagraphWhenSelectionIsEmpty中的错误:
把

var fontWeight = (btnItalics.IsChecked ?? false) ? FontWeights.Bold : FontWeights.Normal;

改为

var fontWeight = (btnBold.IsChecked ?? false) ? FontWeights.Bold : FontWeights.Normal;

修复后即可解决格式偏移问题,同时逻辑更简洁,性能也优于逐字符遍历的实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 10:09:00