【问题标题】:Scroll a WPF FlowDocumentScrollViewer from code?从代码中滚动 WPF FlowDocumentScrollViewer?
【发布时间】:2017-07-02 00:54:31
【问题描述】:

我有一个 FlowDocumentScrollViewer 我想自动滚动到底部 添加文本时。

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

在代码中,我将内联添加到段落中,但是当文本过多时,我会 希望能够使用代码简单地向下滚动,而不是让用户这样做。

有什么建议吗?

【问题讨论】:

    标签: c# .net wpf flowdocument


    【解决方案1】:

    尝试:

    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;
         }
      }
    

    【讨论】:

    • 我得到错误,这不能转换为 DependencyObject
    【解决方案2】:

    我也遇到过类似的问题:我想要一个文本区域,它可以容纳我的文本,能够包装它,它填充它的父控件并且是可滚动的。

    首先我尝试将 TextBlock 与 ScrollViewer 一起使用,我认为它有效,但出于某种原因,我想使用 FlowDocument 而不是 FlowDocumentScrollViewer。后者不起作用,我就是不能让战斗无人看管,所以我试图找到解决方案,这就是我到达这里的原因。我尝试应用原始问题的答案中提供的解决方法,但是这两种解决方案都不适合我(我使用的是 .NET 4.5,也许它适用于其他版本,但我不知道)。

    我也尝试过单独使用一个 FlowDocument,但该控件包含一些我不想要的 UI 元素。所以,我想出了另一个解决方案。

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

    没错。有用!调用 ScrollViewer.ScrollToBottom() 就可以了! ScrollViewer 启用滚动,FlowDocumentScrollViewer 从 FlowDocument 中移除 UI 元素。希望对您有所帮助!


    显然我的构造有一个缺陷,因为这种方式 FlowDocument 不能通过鼠标的滚轮滚动。但是将 FlowDocumentScrollViewer 控件的 IsHitTestVisible 属性设置为 False 可以解决此问题。

    【讨论】:

    • 当心 IsHitTestVisible - 它会禁止在 FlowDocumentScrollViewer 中选择文本
    【解决方案3】:

    这里给出的其他答案有点令人费解,因为我在 FlowDocumentScrollViewer 上没有看到任何公共的“ScrollViewer”属性。

    我解决了这样的问题。注意这个方法在初始化时可能会返回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;
    }
    

    【讨论】:

    • 感谢您指出我回答中的错误。我更正了。
    • 请注意,此 FindScrollViewer 方法目前不起作用,但 John Myczek 的答案中的版本可以。
    • “当前”是指在 WPF 4.0 中吗?再看一遍,由于版本或样式导致 FlowDocumentScrollViewer 和 ScrollViewer 之间的确切控件发生更改,它可能会变得脆弱和损坏,因此更简单和更无知的方法可能会更好。
    【解决方案4】:

    这个问题是 7 年前提出的,现在我遇到了同样的问题,我找到了一个简单的解决方案。以下代码在 Flowdocument 中添加一个与 Paragraph 相同的 Section,然后滚动到末尾。

    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();
        }
    }
    

    【讨论】:

      【解决方案5】:

      这可能是一个很晚的答案,但我已经找到了一种方法。

      //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 了解详情。

      希望对你有帮助。

      【讨论】:

        猜你喜欢
        • 2021-07-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多