0

How to scroll to the top of a FlowDocumentReader?

Content is set by binding

<FlowDocumentReader Grid.Row="4" Grid.Column="0" Name="FlowDocumentPageViewer1" HorizontalAlignment="Stretch">
    <FlowDocumentReader.Document>
        <Binding ElementName="_this" Path="DocFlow" IsAsync="False" Mode="OneWay"/>
    </FlowDocumentReader.Document>                   
</FlowDocumentReader>

If I scroll down then bind new content it does not scroll to the top.
With new content I want to scroll to the top.

Based on comment from Clemnes this scrolls to the top

FlowDocumentPageViewer1.Document.BringIntoView();

Now my problem is how to automate that call.
I cannot put it in the get as cannot put that command after the return.
Tried these two events but are not fired with a binding update

Loaded="FlowDocumentPageViewer1_loaded"  
SourceUpdated="FlowDocumentPageViewer1_loaded"
paparazzo
  • 44,497
  • 23
  • 105
  • 176
  • In code behind you would call `BringIntoView()` on the Document. If there is no simpler way you may have to create and bind an attached property that sets `Document` and also brings it into view. – Clemens Aug 28 '13 at 15:15
  • @Clemens BringIntoView() on the Document does not bring scroll to the top. I am able to call Document.BringIntoView() but it does nothing as the Document is already in view. – paparazzo Aug 28 '13 at 22:43
  • Strange, it does exactly that for me when I switch between documents. I have scrolled down in one document, then set the Document property to some other document. Without BringIntoView the new document is also scrolled down to some position similar to the one of the previous document. With BringIntoView it scrolls straight to the top. – Clemens Aug 29 '13 at 06:54
  • @Clemens I tried again and if I use FlowDocumentReader.Document it works but calling it directly on the Document did not. Now my problem is how to automate that call when any new document is loaded. – paparazzo Aug 29 '13 at 13:02
  • Calling `FlowDocumentPageViewer1.Document.BringIntoView()` was what I meant, maybe I wasn't clear enough. I'll think about how to put it into an attached property. – Clemens Aug 29 '13 at 13:56

1 Answers1

1

You may create an attached property that sets the original Document property and also calls BringIntoView():

public class FlowDocumentReaderEx
{
    public static readonly DependencyProperty DocumentProperty =
        DependencyProperty.RegisterAttached(
            "Document", typeof(FlowDocument), typeof(FlowDocumentReaderEx),
            new FrameworkPropertyMetadata(DocumentPropertyChanged));

    public static FlowDocument GetDocument(DependencyObject obj)
    {
        return (FlowDocument)obj.GetValue(DocumentProperty);
    }

    public static void SetDocument(DependencyObject obj, FlowDocument value)
    {
        obj.SetValue(DocumentProperty, value);
    }

    private static void DocumentPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        var flowDocumentReader = obj as FlowDocumentReader;

        if (flowDocumentReader != null)
        {
            flowDocumentReader.Document = e.NewValue as FlowDocument;

            if (flowDocumentReader.Document != null)
            {
                flowDocumentReader.Document.BringIntoView();
            }
        }
    }
}

Now you can bind this property like:

<FlowDocumentReader ...
    local:FlowDocumentReaderEx.Document="{Binding DocFlow, ElementName=_this}"/>
Clemens
  • 123,504
  • 12
  • 155
  • 268
  • Thanks I might finish testing today as I am not familiar with DependencyProperty and I need to learn it before using it in a production app. – paparazzo Aug 29 '13 at 16:45