Прокрутка WPF FlowDocumentScrollViewer из кода?

У меня есть FlowDocumentScrollViewer, который я хочу автоматически прокрутить вниз при добавлении текста.

<FlowDocumentScrollViewer Name="Scroller">
 <FlowDocument Foreground="White" Name="docDebug" FontFamily="Terminal">
  <Paragraph Name="paragraphDebug"/>
 </FlowDocument>
</FlowDocumentScrollViewer>

в коде я добавляю строки в абзац, но когда есть много текста, я бы хотелось бы иметь возможность просто прокручивать вниз с помощью кода вместо того, чтобы пользователь делал это.

какие предложения?

5 ответов


другие ответы, приведенные здесь, немного озадачивают, так как я не вижу никакого публичного свойства "ScrollViewer" в FlowDocumentScrollViewer.

я взломал проблему, как это. Помните, что этот метод может вернуть null во время инициализации:

public static ScrollViewer FindScrollViewer(this FlowDocumentScrollViewer flowDocumentScrollViewer)
{
    if (VisualTreeHelper.GetChildrenCount(flowDocumentScrollViewer) == 0)
    {
        return null;
    }

    // Border is the first child of first child of a ScrolldocumentViewer
    DependencyObject firstChild = VisualTreeHelper.GetChild(flowDocumentScrollViewer, 0);
    if (firstChild == null)
    {
        return null;
    }

    Decorator border = VisualTreeHelper.GetChild(firstChild, 0) as Decorator;

    if (border == null)
    {
        return null;
    }

    return border.Child as ScrollViewer;
}

попробуй:

Scroller.ScrollViewer.ScrollToEnd();

где "Scroller" - это имя вашего FlowDocumentScrollViewer.

редактировать: я написал этот ответ слишком быстро. FlowDocumentScrollViewer не предоставляет свойство ScrollViewer. Я фактически расширил класс FlowDocumentScrollViewer и реализовал свойство ScrollViewer самостоятельно. Вот реализация:

  /// <summary>
  /// Backing store for the <see cref="ScrollViewer"/> property.
  /// </summary>
  private ScrollViewer scrollViewer;

  /// <summary>
  /// Gets the scroll viewer contained within the FlowDocumentScrollViewer control
  /// </summary>
  public ScrollViewer ScrollViewer
  {
     get
     {
        if (this.scrollViewer == null)
        {
           DependencyObject obj = this;

           do
           {
              if (VisualTreeHelper.GetChildrenCount(obj) > 0)
                 obj = VisualTreeHelper.GetChild(obj as Visual, 0);
              else
                 return null;
           }
           while (!(obj is ScrollViewer));

           this.scrollViewer = obj as ScrollViewer;
        }

        return this.scrollViewer;
     }
  }

я столкнулся с подобной проблемой: я хотел текстовая область который может содержать мой текст, может обернуть его, он заполняет родительский элемент управления и прокручивается.

сначала я попытался использовать TextBlock С ScrollViewer и я думаю, что это сработало, но по какой-то причине я хотел использовать FlowDocument вместо с FlowDocumentScrollViewer. Последнее не сработало, и я просто не мог оставить бой без присмотра. поэтому я попытался найти решения, и вот как я попал сюда. Я попытался применить обходные пути, представленные в ответах на исходный вопрос, однако ни одно из решений не сработало для меня (я использую .NET 4.5, возможно, он работает в других версиях, но я не знаю об этом).

Я пробовал использовать один FlowDocument сам по себе, но элемент управления содержит некоторые элементы пользовательского интерфейса, которые я не хотел. Поэтому я придумал другое решение.

  <ScrollViewer VerticalScrollBarVisibility="Auto">
    <FlowDocumentScrollViewer HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
      <FlowDocument>

Это верно. Он работает! Зову ScrollViewer.ScrollToBottom() просто работает! The ScrollViewer включает прокрутку и FlowDocumentScrollViewer удаляет элементы пользовательского интерфейса от FlowDocument. Надеюсь, это поможет!


видимо, у моей конструкции был недостаток, потому что таким образом FlowDocument не прокручивается через колесо прокрутки мыши. Однако установка FlowDocumentScrollViewer управления IsHitTestVisible свойство False решает эту.


этот вопрос был задан 7 лет назад, сейчас у меня такая же проблема, и я нашел простое решение. Следующий код добавляет раздел в Flowdocument, который то же самое к абзацу, а затем прокрутите до конца.

private void addSection(Section section)
{
    section.Loaded += section_Loaded;
    fdoc.Blocks.Add(section);
}

private void section_Loaded(object sender, RoutedEventArgs e)//scroll to end
{
    var sec = sender as Section;
    if (sec != null)
    {
        sec.BringIntoView();
    }
}

Это может быть очень поздний ответ, но я нашел способ сделать это.

//after your FlowDocumentScrollViewer(for example, x:Name="fdsv") loaded
ScrollViewer sv = fdsv.Template.FindName("PART_ContentHost", fdsv) as ScrollViewer;

sv.ScrollToBottom();
sv.ScrollToTop();
sv.ScrollToVerticalOffset(100);
// etc.

Регистрация IScrollInfo и ScrollViewer для сведения.

надеюсь, это вам поможет.