为什么不计算WPF richtextbox中的所有页面? [英] Why aren't all the pages in the WPF richtextbox getting calculated?

查看:83
本文介绍了为什么不计算WPF richtextbox中的所有页面?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里做的是将文件作为 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日停止循环,无法获取所有页面行文本指针。



我也尝试使用Dispatcher

 Application.Current.Dispatcher.Invoke(Sub( )nextpagept = nextpagept.GetLineStartPosition(CurrDoc.NoLinesPerPage,pcount))

具有相同的结果。

但在所有情况下,如果我插入了一个MsgBox中断循环,它得到所有18页。



我在这里做错了什么?

解决方案

好吧,通过进一步的修补,我似乎找到了问题。

看来这不是我的Sub中的线程问题,而是我运行子的事实在richtextbox中加载 Flowdocument 后立即UpdatePageLinePositions(),也许是因为flowdocument被异步加载,而不是当我的Sub运行时,ll的行已经装好了。

因此找到了不完整的行/页数。



所以我在 RichTextBox <的 TextChanged 事件中放置了Sub UpdatePageLinePositions() / 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 of RichTextBox Adorners), to the end of the FlowDocument.

The problem is, when I load my FlowDocument 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 the TextPointers 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 if pcount 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 my PageLinePointers list count is only 12 or 13.

However, if I don't comment out the MsgBox(pcount) within the While loop, so that the value "36" gets messaged 18 times, then I get all 18 PageLinePointers, 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 few

nextpagept.GetLineStartPosition

calls 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 Dispatcher

Application.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 sub UpdatePageLinePositions() immediately after loading the Flowdocument 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 Sub UpdatePageLinePositions() in the TextChanged event of the RichTextBox, which apparently fires only after all the lines have been loaded in, and all my lines get counted so all the Adorner 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 tried

While 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆