Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the lines of the TextBlock according to the TextWrapping property?

I have a TextBlock in WPF application.

The (Text, Width, Height, TextWrapping, FontSize, FontWeight, FontFamily) properties of this TextBlock is dynamic (entered by the user at the runtime).

Every time the user changes one of the previous properties, the Content property of the TextBlock is changed at the runtime. (everything is ok until here)

Now, I need to get the lines of that TextBlock according to the previously specified properties.
That means I need the lines that TextWrapping algorithms will result.

In other words, I need each line in a separated string or I need one string with Scape Sequence \n.

Any Idea to do that?

like image 356
Hakan Fıstık Avatar asked May 21 '15 15:05

Hakan Fıstık


1 Answers

I would have been surprised if there is no public way of doing that (although one never knows, especially with WPF).
And indeed looks like TextPointer class is our friend, so here is a solution based on the TextBlock.ContentStart, TextPointer.GetLineStartPosition and TextPointer.GetOffsetToPosition:

public static class TextUtils
{
    public static IEnumerable<string> GetLines(this TextBlock source)
    {
        var text = source.Text;
        int offset = 0;
        TextPointer lineStart = source.ContentStart.GetPositionAtOffset(1, LogicalDirection.Forward);
        do
        {
            TextPointer lineEnd = lineStart != null ? lineStart.GetLineStartPosition(1) : null;
            int length = lineEnd != null ? lineStart.GetOffsetToPosition(lineEnd) : text.Length - offset;
            yield return text.Substring(offset, length);
            offset += length;
            lineStart = lineEnd;
        }
        while (lineStart != null);
    }
}

There is not much to explain here
Get the start position of the line, subtract the start position of the previous line to get the length of the line text and here we are.
The only tricky (or non obvious) part is the need to offset the ContentStart by one since by design The TextPointer returned by this property always has its LogicalDirection set to Backward., so we need to get the pointer for the same(!?) position, but with LogicalDirection set to Forward, whatever all that means.

like image 77
Ivan Stoev Avatar answered Sep 23 '22 01:09

Ivan Stoev