如何返回RichTextBox中特定单词的确切范围

时间:2015-05-20 18:50:33

标签: c# wpf indexof textrange

尝试在WPF Richtextbox中选择并着色特定单词,但我的方法只选择单词的前5个字母。索引0,1和2似乎是空字符串,尽管我的rtb中的第一个单词是" private"它之前没有空字符串。

造成这个问题的原因是什么?

public  void FormatRtbText(RichTextBox rtb)
    {
        int x, y;
        string str = "private";

        var text = new TextRange(rtb.Document.ContentStart, rtb.Document.ContentEnd).Text;

        x = text.IndexOf(str);
        y = x + str.Length;

        var range = new TextRange(rtb.Document.ContentStart.GetPositionAtOffset(x), rtb.Document.ContentStart.GetPositionAtOffset(y));
        range.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Red);

    }

2 个答案:

答案 0 :(得分:1)

GetPositionAtOffset在计算偏移时将3个事物视为符号:

  

TextElement元素的开始或结束标记。

     

InlineUIContainer或BlockUIContainer中包含的UIElement元素。注意   这样的UIElement总是被算作一个符号;任何   UIElement包含的其他内容或元素不是   算作符号。

     

文本Run中的16位Unicode字符   元件。

此处前两个符号是ParagraphRun元素。因此,TextRange是您想要的两个符号。这段代码应该是工作。 (此代码所做的只是跳过符号,直到下一个符号为文本。)

TextPointer start = rtb.Document.ContentStart;
while (start.GetPointerContext(LogicalDirection.Forward) != TextPointerContext.Text)
{
    start = start.GetNextContextPosition(LogicalDirection.Forward);
    if (start == null) return;
}
...
var range = new TextRange(start, start.GetPositionAtOffset(y));

答案 1 :(得分:0)

我发现wpf rtf框返回的偏移几乎一文不值。他们没有考虑文本框所需的隐藏字符。框中的每个新段落,图像等都会添加更多隐藏偏移的字符。

以下是我提出的搜索与插入位置相关的比赛的内容。

  private TextRange FindText(string findText)
    {
      var fullText = DoGetAllText();
      if (string.IsNullOrEmpty(findText) || string.IsNullOrEmpty(fullText) || findText.Length > fullText.Length)
        return null;

      var textbox = GetTextbox();
      var leftPos = textbox.CaretPosition;
      var rightPos = textbox.CaretPosition;

      while (true)
      {
        var previous = leftPos.GetNextInsertionPosition(LogicalDirection.Backward);
        var next = rightPos.GetNextInsertionPosition(LogicalDirection.Forward);
        if (previous == null && next == null)
          return null; //can no longer move outward in either direction and text wasn't found

        if (previous != null)
          leftPos = previous;
        if (next != null)
          rightPos = next;

        var range = new TextRange(leftPos, rightPos);
        var offset = range.Text.IndexOf(findText, StringComparison.InvariantCultureIgnoreCase);
        if (offset < 0)
          continue; //text not found, continue to move outward

        //rtf has broken text indexes that often come up too low due to not considering hidden chars.  Increment up until we find the real position
        var findTextLower = findText.ToLower();
        var endOfDoc = textbox.Document.ContentEnd.GetNextInsertionPosition(LogicalDirection.Backward);
        for (var start = range.Start.GetPositionAtOffset(offset); start != endOfDoc; start = start.GetPositionAtOffset(1))
        {
          var result = new TextRange(start, start.GetPositionAtOffset(findText.Length));
          if (result.Text?.ToLower() == findTextLower)
          {
            return result;
          }
        }
      }
    }

如果你想突出显示匹配,那么就像将此方法更改为无效并在找到匹配项时执行此操作一样简单:

textbox.Selection.Select(result.Start, result.End);