Question

I have a TextPointer tp pointing to the start of a phrase which I'd like to highlight using a TextRange. However this code:

TextRange tr = new TextRange(tp, tp.GetPositionAtOffset(phrase.Length));
Debug.WriteLine("phrase:" + phrase + ", len=" + phrase.Length + " and tr length=" + tr.Text.Length + " and tr.text=" + tr.Text + "<");

Produces the incorrect output:

phrase:mousse au chocolat, len=18 and tr length=15 and tr.text=mousse au choco<

I used the following to retrieve the starting location of the phrase in my document:

x = tr.Text.IndexOf(phrase);

How do you get a substring TextRange given a string phrase and a TextRange for the document?

The following answer shows MSDN sample code for finding a word:

https://stackoverflow.com/a/984836/317033

However it doesn't seem to work with phrases in my case. Per the documentation: http://msdn.microsoft.com/en-us/library/ms598662(v=vs.110).aspx The GetPositionAtOffset offset includes 'symbols' which aren't just the visible characters. Thus the sample code doesn't work properly either as you can't just use string.IndexOf() with GetPositionAtOffset.

So it looks like the answer will involve correctly accounting for the non-character elements (symbols in the documentation) that need to be included into the offset. My naive counting the number of runs the phrase spans doesn't work.

Was it helpful?

Solution

The following method do the same as GetPositionAtOffset but count only text characters.

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;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top