WPF Richtextbox Application。查找跨多个运行的文本

问题描述 投票:4回答:2

我正在尝试为WPF richtextbox实现Application.Find命令。假设我要搜索“专家”。听起来很容易。但是由于wpf的性质,如果“专家”中的所有其他字母都以粗体显示,则富文本框将包含e * x * p * e * r * t *,这意味着存在六个运行。我有一个起始的textPointer。我要弄清楚的是如何获取结尾的textPointer,以便可以创建可用于创建Selection的TextRange。

在此示例中,开始的文本指针在第一次运行中,而结束的文本指针在最后一次运行中。如果您知道运行以及运行中的偏移量,是否有一种简单的方法来生成文本指针?我尝试使用第一个textpointer的偏移量生成它,但由于偏移量不在第一次运行之内而无法正常工作。

作为WPF richtextbox的相对新手,我很困惑。我认为这个问题已经得到解决。我确实找到了一个局部解决方案,但它只能在一次运行中使用,而不能解决多次运行的情况。

wpf richtextbox
2个回答
11
投票

想法是找到第一个字符(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));

0
投票

[当我尝试代码时,发生了@YusufTarıkGünaydın提到的问题,所以我将GetTextPositionAtOffset @meziantou的代码修改为此:

TextPointer GetTextPositionAtOffset(TextPointer position, int characterCount)
{
     var ret = position;
     var i = 0;
     while (ret != null)
     {
          string stringSoFar = new TextRange(ret, ret.GetPositionAtOffset(i, LogicalDirection.Forward)).Text;
          if (stringSoFar.Length == characterCount)
              break;
          i++;
          if (ret.GetPositionAtOffset(i, LogicalDirection.Forward) == null)
          return ret.GetPositionAtOffset(i - 1, LogicalDirection.Forward);

     }
     ret = ret.GetPositionAtOffset(i, LogicalDirection.Forward);
     return ret;
    }

而且效果很好。

© www.soinside.com 2019 - 2024. All rights reserved.