为什么不计算WPF richtextbox中的所有页面? [英] Why aren't all the pages in the WPF richtextbox getting calculated?
问题描述
我在这里做的是将文件作为 XamlPackage
加载到RichTextBox中。加载后,我计算每页的行数(NoLinesPerPage)(从预设的上/下边距和目标纸张高度)。
我正在使用的特定值给了我36行数每页。
现在,我想在软分页符(每36行)绘制一行,所以我试图获取GetCharacterRect(LogicalDirection.Forward)每36行第一个字符的.Y值(Y值然后传递给一组 RichTextBox
Adorner
s),到FlowDocument的末尾。
问题是,当我加载 FlowDocument
并运行要经历每36行的子程序,我不会一直到最后。只有大约前75%左右。
我在每36行获得 TextPointer
的例行程序是因此:
私人 Sub UpdatePageLinePositions()
Dim PageLinePointers As 新列表( TextPointer)
Dim tpointer As TextPointer = Dox.Document.ContentStart.GetLineStartPosition( 0 )
Dim ypoint 作为 整数 = 0
Dim charrect As Rect = 没什么
Dim nextpagept As TextPointer = tpointer
Dim lastpage As Boolean = False
lastpage = False
Dim pcount 作为 整数 = < span class =code-digit> 0
nextpagept = nextpagept.GetLineStartPosition(CurrDoc.NoLinesPerPage,pcount)
If pcount = CurrDoc.NoLinesPerPage 然后
' MsgBox(pcount)
PageLinePointers.Add(nextpagept)
否则
lastpage = True
结束 如果
结束 虽然
MsgBox(PageLinePointers.Count)
对于 每个 plp As TextPointer In PageLinePointers
charrect = plp.GetCharacterRect(LogicalDirection.Forward )
AdornerLayer.GetAdornerLayer(Dox).Add( New LineAdorner(Dox,charrect.Y))
下一步 plp
(如果 pcount
小于跳过的行数(这意味着它位于文档的末尾)。
现在,对于我的测试文档,我应该d得出19页(18个装饰者),但是当我加载文档时,我只得到12个,或者有时候13个(最后~25%的文档没有可见的装饰,我的 PageLinePointers
列表数量只有12或13.
但是,如果我没有注释掉 MsgBox(pcount)
在 while
循环中,以便值36收到18次消息,然后我得到所有18 PageLinePointers
,我的FlowDocument上可以看到所有18个页面的线条装饰。
我尝试了什么:
因此,我猜测这必须是一个线程问题,它的循环过快并且在最后几个
nextpagept.GetLineStartPosition之前到达终点(lastpage = true) / pre>调用,返回的值实际上被添加到List。
所以我尝试了作为同步任务运行:
Dim mytask As New Task(Sub()nextpagept = nextpagept.GetLineStartPosition(CurrDoc.No) LinesPerPage,pcount))
mytask.RunSynchronously()
循环内的
,但仍然在12日或13日停止循环,无法获取所有页面行文本指针。
我也尝试使用DispatcherApplication.Current.Dispatcher.Invoke(Sub( )nextpagept = nextpagept.GetLineStartPosition(CurrDoc.NoLinesPerPage,pcount))具有相同的结果。
但在所有情况下,如果我插入了一个MsgBox中断循环,它得到所有18页。
我在这里做错了什么?解决方案
好吧,通过进一步的修补,我似乎找到了问题。
看来这不是我的Sub中的线程问题,而是我运行子的事实在richtextbox中加载
,也许是因为flowdocument被异步加载,而不是当我的Sub运行时,ll的行已经装好了。Flowdocument
后立即UpdatePageLinePositions()
因此找到了不完整的行/页数。
所以我在RichTextBox <的
TextChanged
事件中放置了SubUpdatePageLinePositions()
/ code>,显然只有在所有行都被加载后才会触发,并且我的所有行都被计算在内,所以所有Adorner
Y位置都会被计算出来。 />
虽然这样做会使Sub在每次文本更改后运行,这绝对不可取。理想情况下,它只会在初始文档加载后运行。
(顺便说一下,我尝试过而 不 RichTextBox.Document.isLoaded:结束,以获取文档加载点,但它似乎还为时尚早(仍然没有得到所有的线)。所以我已经确定了
TextChanged
。
What I'm doing here is loading a file into a RichTextBox as an
XamlPackage
. Once loaded, I calculate the number of lines per page (NoLinesPerPage) (from preset top/bottom margins and target paper height).
The particular values I'm working with give me a number of 36 lines per page.
Now, I want to draw lines at soft page breaks (every 36 lines), so I'm trying to get the GetCharacterRect(LogicalDirection.Forward).Y values for the first character of every 36 lines (Y values which I then pass to a set ofRichTextBox
Adorner
s), to the end of the FlowDocument.
The problem is, when I load myFlowDocument
and run the subroutine to go through every 36 lines, I'm not getting them all the way through to the end. Only about the first 75% or so.
My routine for getting theTextPointer
s at each 36th line is thus:
Private Sub UpdatePageLinePositions() Dim PageLinePointers As New List(Of TextPointer) Dim tpointer As TextPointer = Dox.Document.ContentStart.GetLineStartPosition(0) Dim ypoint As Integer = 0 Dim charrect As Rect = Nothing Dim nextpagept As TextPointer = tpointer Dim lastpage As Boolean = False While lastpage = False Dim pcount As Integer = 0 nextpagept = nextpagept.GetLineStartPosition(CurrDoc.NoLinesPerPage, pcount) If pcount = CurrDoc.NoLinesPerPage Then 'MsgBox(pcount) PageLinePointers.Add(nextpagept) Else lastpage = True End If End While MsgBox(PageLinePointers.Count) For Each plp As TextPointer In PageLinePointers charrect = plp.GetCharacterRect(LogicalDirection.Forward) AdornerLayer.GetAdornerLayer(Dox).Add(New LineAdorner(Dox, charrect.Y)) Next plp
(I end the loop ifpcount
is less than the skipped number of lines (which means it is at the end of the document).
Now, for my test document, I should come up with 19 pages (18 adorners), but when I load the document I only get 12, or sometimes 13 (the last ~25% of the document has no visible adorners, and myPageLinePointers
list count is only 12 or 13.
However, if I don't comment out theMsgBox(pcount)
within theWhile
loop, so that the value "36" gets messaged 18 times, then I get all 18PageLinePointers
, and all 18 page line adorners are visible on my FlowDocument.
What I have tried:
So, I guessed this must be a threading issue, it's looping too fast and reaching the end (lastpage=true) before the last fewnextpagept.GetLineStartPositioncalls are made, and the returned values actually get added to the List.
So I tried a running as a synchronous Task:
Dim mytask As New Task(Sub() nextpagept = nextpagept.GetLineStartPosition(CurrDoc.NoLinesPerPage, pcount)) mytask.RunSynchronously()
inside the Loop, but it still stops at the 12th or 13th loop, failing to get all of the page line textpointers.
I also tried with a DispatcherApplication.Current.Dispatcher.Invoke(Sub() nextpagept = nextpagept.GetLineStartPosition(CurrDoc.NoLinesPerPage, pcount))with the same result.
But in all cases, if I have the interruption of a MsgBox inserted in the loop, it gets all 18 pages.
What am I failing to do correctly here?解决方案Ok, with further tinkering I seem to have found the problem.
It seems it was not an issue of threading in my Sub, but rather the fact that I was running the subUpdatePageLinePositions()
immediately after loading theFlowdocument
in the richtextbox, and perhaps because the flowdocument gets loaded asynchrously, not all of the lines are quite yet loaded by the time my Sub gets run.
Hence the incomplete number of lines/pages found.
So I've placed the SubUpdatePageLinePositions()
in theTextChanged
event of theRichTextBox
, which apparently fires only after all the lines have been loaded in, and all my lines get counted so all theAdorner
Y positions get calculated.
Although, doing so makes the Sub get run after every text change, which is definitely not desirable. Ideally it would only run after the initial document load.
(Incidentally I triedWhile Not RichTextBox.Document.isLoaded:End While, to get the document loaded point, but it seems that is still too early (still doesn't get all of the lines). So I've settled on
TextChanged
.
这篇关于为什么不计算WPF richtextbox中的所有页面?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!