WPF TextBlock get lines after textwrapping
Asked Answered
K

1

6

I have FixedDocument page and I want to place TextBlock on it, but it can be that Textblock doesn't fit on page by height.
So I want to take lines from generated TextBlock with TextWrapping, and then create new TextBlock, that fitted by height and place it on page.
TextBlock have LineCount private property, that mean that it has TextLines after wrapping and I can somehow get it.
Creating TextBlock with runs:

public TextItem(PageType pageType, Run[] runs, Typeface typeFace, double fontSize)
        : base(pageType)
{
     this.TextBlock = new TextBlock();
     this.TextBlock.Inlines.AddRange(runs);
     if (typeFace != null)
          this.TextBlock.FontFamily = typeFace.FontFamily;

     if (fontSize > 0)
           this.TextBlock.FontSize = fontSize;
     this.TextBlock.TextWrapping = TextWrapping.Wrap;   //wrapping
}

Creating TextBlock with text:

public TextItem(PageType pageType, String text, Typeface typeFace, double fontSize)
        : base(pageType)
{
    if (typeFace == null || fontSize == 0)
        throw new Exception("Wrong textitem parameters");

    this.TextBlock = new TextBlock();
    this.TextBlock.Text = text;
    this.TextBlock.FontFamily = typeFace.FontFamily;
    this.TextBlock.FontSize = fontSize;
    this.TextBlock.TextWrapping = TextWrapping.Wrap;
    this.TextBlock.TextAlignment = TextAlignment.Justify;

    this.TypeFace = typeFace;
}

Set width to TextBlock and get DesiredSize :

this.TextBlock.Width = document.CurrentPage.Content.ActualWidth;
this.TextBlock.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
Kermanshah answered 16/1, 2013 at 10:19 Comment(3)
pastebin.com/b6cZD5pp I know one way to get lines from textblock, but this only work when control was already drawned.Kermanshah
Have you looked at the wpf FlowDocument? A link to msdn.Dribble
Yes, but FlowDocument does not suitable for me. Im try layout elements manual on single FixedPage, that have A4 size. Thats why i need to split textblock if it does not fit.Kermanshah
S
2

I faced the exactly same problem, and for some time, I lost the hope and I thought there is no solution for this.
BUT, I was wrong, there are many solutions for that (At least three)
And you are right, one of them use the LineCount property by using reflection.
And the second using it is own algorithm to get the lines.
And the third, which is preferred to me, has very elegant way to get the result which you want.

Please refer to this question, to see the three answers of this.
Get the lines of the TextBlock according to the TextWrapping property?


Here is a copy of the best solution (in my opinion)
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);
    }
}
Salimeter answered 20/10, 2015 at 8:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.