Search code examples
wpfflowdocument

WPF Flowdocument paragraph.BringIntoView() is not working for new documents


I want to load big .rtf file and scroll to specific paragraph in it.

So I do something like this:

    private FlowDocument GenerateDocument(string path)
    {
        var doc = new FlowDocument();
        using (FileStream fs = File.Open(path, FileMode.Open, FileAccess.Read))
        {
            var content = new TextRange(doc.ContentStart, doc.ContentEnd);
            content.Load(fs, DataFormats.Rtf);
        }
        return doc;
    }

Then, I look up for bookmarked paragraph and want to scroll there. Something like this:

    private void ScrollToBookmark(string bookmark)
    {
        Paragraph p = LookUp(bookmark);
        if (p != null) p.BringIntoView();
    }

LookUp is a fucntion to find desired paragraph, it works well, and return Paragraph in previosly loaded Document.

And... Nothing happens. Any tips?

I use FlowDocumentReader to show my Flowdocument. BringIntoView is not working both in ScrollMode and PageMode.

Direct access to scrollviewer of FlowDocumentReader through logical tree and manipulating with it is not an option. I simply don't know where to scroll and prefer to not use any "hacks" if it is possible.


Solution

  • Ok, I found an issue.

    Problem is, when you load new FlowDocument, paragraphs loading asynchronously, so if you call paragraph.BringIntoView() right after you loaded document - paragraph does not exists yet, so nothing happens.

    Here is some details: https://support.microsoft.com/en-us/kb/959084

    You need to check paragraph.IsLoaded property and if it is not loaded yet, you need to catch Loaded event and invoke BringIntoView() there.

    Here is code I used and it works perfectly:

        private void BringToViewParagraph(Paragraph paragraph)
        {
            if (paragraph.IsLoaded) paragraph.BringIntoView();
            else
            {
                paragraph.Loaded += paragraphLoaded;
            }
        }
    
        void paragraphLoaded(object sender, RoutedEventArgs e)
        {
            Paragraph paragraph = (Paragraph)sender;
            paragraph.Loaded -= paragraphLoaded;
            paragraph.BringIntoView();
        }