mycenean Ответов: 1

Почему не все страницы в WPF richtextbox вычисляются?


То, что я здесь делаю, - это загрузка файла в RichTextBox в качестве XamlPackage После загрузки я вычисляю количество строк на странице (NoLinesPerPage) (исходя из заданных верхних/нижних полей и целевой высоты бумаги).
Конкретные значения, с которыми я работаю, дают мне число 36 строк на странице.

Теперь я хочу рисовать линии на мягких разрывах страниц (каждые 36 строк), поэтому я пытаюсь получить GetCharacterRect(LogicalDirection.Вперед).Значения Y для первого символа каждых 36 строк (значения Y, которые я затем передаю набору RichTextBox Adorners), до конца FlowDocument.

Проблема в том, что когда я загружаю свой FlowDocument и запустите подпрограмму, чтобы пройти через каждые 36 строк, я не получу их полностью до конца. Только около первых 75% или около того.

Моя рутина для получения TextPointers в каждой 36-й строке таким образом:

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


(Я заканчиваю цикл, если pcount меньше пропущенного количества строк (что означает, что оно находится в конце документа).
Теперь для моего тестового документа я должен придумать 19 страниц (18 украшателей), но когда я загружаю документ, я получаю только 12, а иногда и 13 (последние ~25% документа не имеют видимых украшателей, и мой PageLinePointers количество списков составляет всего 12 или 13.

Однако, если я не буду комментировать MsgBox(pcount) в While цикл, так что значение "36" получает сообщение 18 раз, а затем я получаю все 18 PageLinePointers, и все 18 украшателей строк страницы видны на моем FlowDocument.

Что я уже пробовал:

Итак, я предположил, что это, должно быть, проблема с потоками, она слишком быстро зацикливается и достигает конца (lastpage=true) до последних нескольких
nextpagept.GetLineStartPosition
вызовы выполняются, и возвращаемые значения фактически добавляются в список.

Поэтому я попробовал запустить его как синхронную задачу:

Dim mytask As New Task(Sub() nextpagept = nextpagept.GetLineStartPosition(CurrDoc.NoLinesPerPage, pcount))
            mytask.RunSynchronously()


внутри цикла, но он все равно останавливается на 12-м или 13-м цикле, не сумев получить все текстовые указатели строки страницы.

Я также пытался связаться с диспетчером
Application.Current.Dispatcher.Invoke(Sub() nextpagept = nextpagept.GetLineStartPosition(CurrDoc.NoLinesPerPage, pcount))
с тем же результатом.
Но во всех случаях, если у меня есть прерывание MsgBox, вставленного в цикл, он получает все 18 страниц.

Что я здесь не могу сделать правильно?

1 Ответов

Рейтинг:
1

mycenean

Ладно, с дальнейшим мастерством я, кажется, нашел проблему.
Похоже, это была не проблема резьбы в моей субмарине, а скорее тот факт, что я управлял субмариной UpdatePageLinePositions() сразу же после загрузки Flowdocument в richtextbox и, возможно, из-за того, что flowdocument загружается асинхронно, не все строки еще полностью загружены к тому времени, когда запускается моя Субподрядка.
Отсюда и неполное количество найденных строк/страниц.

Поэтому я разместил на страницах UpdatePageLinePositions() в TextChanged событие года RichTextBox, который, по-видимому, срабатывает только после того, как все линии были загружены, и все мои линии подсчитываются, так что все Adorner Y-позиции вычисляются.

Хотя, делая это, саб запускается после каждого изменения текста, что определенно нежелательно. В идеале он будет работать только после начальной загрузки документа.
(Кстати, я пробовал

While Not RichTextBox.Document.isLoaded:End While
, чтобы получить точку загрузки документа, но кажется, что это еще слишком рано (все еще не получает все строки). Так что я остановился на TextChanged.