【问题标题】:WPF Richtextbox Application.Find Text spanning Multiple runsWPF Richtextbox Application.Find 跨越多次运行的文本
【发布时间】:2022-04-21 06:24:05
【问题描述】:

我正在尝试为 WPF 富文本框实现 Application.Find 命令。假设我正在寻找“专家”。听起来很容易。但是由于 wpf 的性质,如果 "expert" 中的每个其他字母都加粗,则 Richtextbox 包含 e*x*p*e*r* t* 这意味着存在六次运行。我有一个起始文本指针。我想弄清楚的是如何获取结尾的 textPointer 以便我可以创建一个可以用来创建选择的 TextRange。

在这个例子中,起始文本指针在第一次运行,结束文本指针应该在最后一次运行。如果您知道运行和运行中的偏移量,是否有一种简单的方法来生成文本指针?我尝试使用第一个文本指针的偏移量来生成它,但这不起作用,因为偏移量不在第一次运行中。

作为 WPF 富文本框的新手,这个让我很困惑。我想这个问题已经被处理和解决了。我确实找到了一个部分解决方案,但它只适用于单次运行,并不能解决多次运行的情况。

【问题讨论】:

    标签: wpf richtextbox


    【解决方案1】:

    这个想法是找到第一个字符的偏移量 (IndexOf),然后在这个索引处找到 TextPointer(但只计算文本字符)。

    public TextRange FindTextInRange(TextRange searchRange, string searchText)
    {
        int offset = searchRange.Text.IndexOf(searchText, StringComparison.OrdinalIgnoreCase);
        if (offset < 0)
            return null;  // Not found
    
        var start = GetTextPositionAtOffset(searchRange.Start, offset);
        TextRange result = new TextRange(start, GetTextPositionAtOffset(start, searchText.Length));
    
        return result;
    }
    
    TextPointer GetTextPositionAtOffset(TextPointer position, int characterCount)
    {
        while (position != null)
        {
            if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
            {
                int count = position.GetTextRunLength(LogicalDirection.Forward);
                if (characterCount <= count)
                {
                    return position.GetPositionAtOffset(characterCount);
                }
    
                characterCount -= count;
            }
    
            TextPointer nextContextPosition = position.GetNextContextPosition(LogicalDirection.Forward);
            if (nextContextPosition == null)
                return position;
    
            position = nextContextPosition;
        }
    
        return position;
    }
    

    代码的使用方法如下:

    TextRange searchRange = new TextRange(richTextBox.Document.ContentStart, richTextBox.Document.ContentEnd);
    TextRange foundRange = FindTextInRange(searchRange, "expert");
    foundRange.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(Colors.Red));
    

    【讨论】:

    • 非常感谢 meziatou。我现在就试试这个!
    • 我迷失在杂草丛中——这比我走的路好 100 倍。它工作得很好。谢谢美子头!我确实需要调整它以添加一个匹配整个单词的选项,但我想我可以从这里弄清楚。
    • 抱歉,显然我没有足够的 stackoverflow“声誉”来投票,但如果可以的话,我会的。
    • 很好的解决方案,但是有一个小问题。 GetTextRunLength 不考虑 \r\n 字符。如果你在searchRange.Text 中有这些,那么生成的 TextRange 将在正确位置之前新行字符的数量。
    【解决方案2】:

    我在此 GitHub 页面上找到了更完整的解决方案。 https://github.com/manasmodak/WpfSearchAndHighlightText

    它能够很好地处理 \n 和 \r 并且没有我在其他解决方案中处理的错误。

    【讨论】:

      猜你喜欢
      • 2011-08-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-29
      • 1970-01-01
      • 1970-01-01
      • 2012-12-15
      相关资源
      最近更新 更多