3

In my System.Windows.Controls.RichTextBox, I would like to find a TextRange of a given word. However, it is not giving me the correct PositionAtOffset after the first found word. The first one is correct, and then for the next found words, the position is not correct. Am I using the correct methods?

Loop through listOfWords

Word= listOfWords[j].ToString();

startPos = new TextRange(transcriberArea.Document.ContentStart, transcriberArea.Document.ContentEnd).Text.IndexOf(Word.Trim());

 leftPointer = textPointer.GetPositionAtOffset(startPos + 1, LogicalDirection.Forward);

rightPointer = textPointer.GetPositionAtOffset((startPos + 1 + Word.Length), LogicalDirection.Backward);
TextRange myRange= new TextRange(leftPointer, rightPointer);
paradisonoir
  • 2,892
  • 9
  • 30
  • 41

2 Answers2

13

This code adapted from a sample at MSDN will find words in from a specified position.

TextRange FindWordFromPosition(TextPointer position, string word)
{
    while (position != null)
    {
        if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
        {
            string textRun = position.GetTextInRun(LogicalDirection.Forward);

            // Find the starting index of any substring that matches "word".
            int indexInRun = textRun.IndexOf(word);
            if (indexInRun >= 0)
            {
                TextPointer start = position.GetPositionAtOffset(indexInRun);
                TextPointer end = start.GetPositionAtOffset(word.Length);
                return new TextRange(start, end);
            }
        }

        position = position.GetNextContextPosition(LogicalDirection.Forward);
    }

    // position will be null if "word" is not found.
    return null;
}

You can then use it like so:

string[] listOfWords = new string[] { "Word", "Text", "Etc", };
for (int j = 0; j < listOfWords.Length; j++)
{
    string Word = listOfWords[j].ToString();
    TextRange myRange = FindWordFromPosition(x_RichBox.Document.ContentStart, Word);
}
Bryce Kahle
  • 8,159
  • 1
  • 23
  • 26
  • TextPointer.GetPositionAtOffset's offset is 'symbols' not characters thus this code won't work in general. Most likely if string word contains spaces or is a non-English language where words can span UIElements. –  Feb 19 '14 at 18:16
0

I think, it should work also.

It is like "find next" any item from the list.

    TextPointer FindWordsFromPosition(TextPointer position, IList<string> words)
    {
        var firstPosition = position;
        while (position != null)
        {
            if (position.GetPointerContext(LogicalDirection.Forward) ==    TextPointerContext.Text)
            {
                string textRun = position.GetTextInRun(LogicalDirection.Forward);

                var indexesInRun = new List<int>();

                foreach (var word in words)
                {
                    var index = textRun.IndexOf(word);

                    if (index == 0)
                        index = textRun.IndexOf(word, 1);

                    indexesInRun.Add(index);
                }

                indexesInRun = indexesInRun.Where(i => i != 0 && i != -1).OrderBy(i => i).ToList();

                if (indexesInRun.Any())
                {
                    position = position.GetPositionAtOffset(indexesInRun.First());
                    break;
                }

                return firstPosition;
            }
            else
                position = position.GetNextContextPosition(LogicalDirection.Forward);
        }

        return position;
    }