I'm trying to split a very long string (document) on several pages containing a TextBlock, however, I need to make each page of specific number of lines which means that I need to split the TextBlock into lines. I tried to create several logics but no luck of getting an accurate thing, but found a solution here (Get the lines of the TextBlock according to the TextWrapping property?) which worked for me on my prototype project then stopped working and gets the whole text in one line. Here is the code from the above topic: public static class TextUtils { public static IEnumerable 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); } } And this is my code: testTB.Text = Functions.GenString(200); foreach (string xc in testTB.GetLines()) { MessageBox.Show(xc); } Where I guess that the issue is that lineStart.GetLineStartPosition(1) is returning null. Any help is appreciated, thanks in advance.

对我来说,您发布的代码看起来容易出错。仅当包含纯文本时它才会起作用TextBlock。但是,当您使用,或 之Inline类的元素时,您不再有纯文本作为内容,还有上下文标记,如内联元素的标签。我想这就是您基于偏移量的失败之处。RunBoldUnderlinestring.Substring TextRange解决方案是从检索到的结果中创建一个TextPointer并通过属性提取纯文本TextRange.Text。 以下实现同时支持:通过TextBlock.Text属性设置的纯文本和使用元素设置的文本Inline: public static IEnumerable GetLines(this TextBlock source) { TextPointer lineStart = source.ContentStart.GetPositionAtOffset(1, LogicalDirection.Forward); do { TextPointer lineEnd = lineStart.GetLineStartPosition(1) ?? source.ContentEnd; var textRange = new TextRange(lineStart, lineEnd); lineStart = lineEnd; yield return textRange.Text; } while (lineStart.IsAtLineStartPosition); } 评论 重要的是要等到TextBlock.Loaded事件被引发。这是因为TextBlock在此过程中将单个文本字符串拆分为多行UIElement.Measure,因为这是控件知道其所需大小以及行的最大可用宽度的时刻。UIElement.Measure当布局加载开始时,由渲染引擎调用。 例子 主窗口.xaml 主窗口.xaml.cs partial class MainWindow : Window { public MainWindow() { this.Loaded += OnLoaded; } private void OnLoaded(object sender, EventArgs e) { var lines = this.TextBlock.GetLines().ToList(); // Returns 54 lines } }

This has few open ended qeustions. Whats the source for this textblock? Did you account for the UI width and length as the textblock may vary based on the UI (be it, windows/web). did you explore the options of scrollbars usage in the textblock or what is the ideal intent of your work?

The text source is stored in a database, for the sake of simplicity let's just say that GenString function generates random string. The TextBlock size is static and in the runtime the string is indeed wrapped into lines. And No, I don't want to use scrollbars. What I'm trying to achieve is simply filling the TextBlock with text until a certain number of lines (which represents the height I need) then get the remaining text to be filled in another page.

TextBlock doesn't have this kind of API as it is designed and optimized for single line text. You could make thing a lot easier when switching to a read-only TextBox. It offers all the API you need. An other solution could be to use the FormattedText` class to measure the text width and calculate line breaks yourself.

Well, the code above once worked before and worked for other people, on a textblock. However, I thought about textboxes but as far as I know, they doesn't provide ability to use inline bold and underline to format what is inside.

我并不是说它不起作用。我只是建议使用它,TextBox因为它提供了一个简单的 API 来获取行数或实际行数。您发布的代码是一个简单的迭代。它不起作用的唯一原因是TextBlockb的内容

I indeed going to face the issue with inlines and formatting but for now I can't even use plain text for some reason, I tried your code and not working as well... Same issue, the function outputs all the text as one line. Can you give me a full working example, maybe I have an issue with my xaml or text assigning methode, maybe you can send me a xaml snippet and a usage sample. Sorry for the hassle I'm causing ...

What can you make wrong when assigning a string to TextBlock.Text. I'm not sure if you are serious. Nevertheless I've added the code I just used to test it. The method returns 54 lines.

Your posted GetLines implementation crashes with the example input.