【问题标题】:Best Way to Scroll to End of ScrollViewer滚动到 ScrollViewer 末尾的最佳方式
【发布时间】:2012-06-23 17:15:58
【问题描述】:

目前,当我添加新项目时,让我的代码自动滚动到末尾的唯一方法如下:

XAML:

<ScrollViewer x:Name="chatViewScroller" HorizontalAlignment="Left" Height="201" Margin="0,32,0,0" VerticalAlignment="Top" Width="475" Background="#7FFFFFFF">
    <StackPanel x:Name="chatViewContent" />
</ScrollViewer>

代码:

                chatViewContent.Children.Add(
                    new TextBlock() {
                        Text = text,
                        FontSize = 18,
                        TextWrapping = Windows.UI.Xaml.TextWrapping.Wrap,
                        Margin = new Thickness(10, 3, 10, 0),
                        Foreground = new Windows.UI.Xaml.Media.SolidColorBrush(
                            isServerMessage ? Windows.UI.Colors.Purple : Windows.UI.Colors.Black)
                    });
                await Task.Delay(10);
                chatViewScroller.ScrollToVerticalOffset(chatViewScroller.ScrollableHeight);

这是公认的做法吗?我必须等待一些随机的时间吗?

【问题讨论】:

  • 您好,您找到更好的解决方案了吗?
  • await Dispatcher.Yield(DispatcherPriority.Input); 可以工作吗?

标签: xaml scroll windows-runtime


【解决方案1】:

使用 ActualHeight 对我不起作用(我还没有弄清楚原因) - 但是像这样使用 ScrollableHeight 可以解决问题:

// adding item to ItemsControl...
// ...
_scrollViewer.UpdateLayout();
_scrollViewer.ScrollToVerticalOffset(_scrollViewer.ScrollableHeight);

【讨论】:

    【解决方案2】:

    对于 Windows Phone 8.1,我使用这个:

    MyScrollViewer.ChangeView(0.0f, double.MaxValue, 1.0f);
    

    【讨论】:

    • 在 Windows 8.1 上也能正常工作
    • 这是对 UWP 应用执行此操作的正确方法。如果您使用 ScrollToVerticalOffset,编译器将为您提供:“ScrollViewer.ScrollToVerticalOffset(double)”已过时:“ScrollToVerticalOffset 可能已更改或无法用于 Windows 8.1 之后的版本。相反,请使用 ChangeView。'
    【解决方案3】:

    在我看来,最好的选择是通过以下方式从 ScrollViewer 继承:

    public partial class AutoScrollViewer
    {        
        public AutoScrollViewer()
        {
            InitializeComponent();
            this.SizeChanged += (sender, args) => this.ScrollToBottom();
        }
    }
    

    和 XAML

    <ScrollViewer x:Class="AutoScrollViewer"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    </ScrollViewer>
    

    然后,您可以直接在 XAML 中使用新类,而无需附加代码,这在您拥有“纯”MVVM 代码时尤其有用。

    【讨论】:

      【解决方案4】:

      在任何语言中,除了 JavaScript 之外,没有随机异步永远不是解决任何问题的答案......它总是有你知道的“代码味道”吗?

      执行此操作的正确方法是通过调用 ScrollViewer.Measure(Size) 同步强制“刷新”ScrollViewer 的度量以包括新添加的子项

      在您“重新测量”后,ScrollableHeight 将是正确的值,您可以像往常一样使用它..

      像这样:

          private void AddMessage(string text, Color color)
          {
              var message = new TextBlock
              {
                  Text = text,
                  FontSize = 18,
                  TextWrapping = TextWrapping.Wrap,
                  Margin = new Thickness(10, 3, 10, 0),
                  Foreground = new SolidColorBrush(color),
              };
      
              chatViewContent.Children.Add(message);
      
              chatViewScroller.Measure(chatViewScroller.RenderSize);
              chatViewScroller.ScrollToVerticalOffset(chatViewScroller.ScrollableHeight);
          }
      

      我们在这里使用的SizeRenderSize,在某些极端情况下技术上可能是不正确的,但对于我们的目的来说它非常接近完美。从技术上讲,您还可以将任意大的 Size 用于 Measure(Size) 并获得相同的效果。无论哪种方式最适合您的解决方案,希望对您有所帮助 -ck

      【讨论】:

      • .Measure 在 WinRT 中有效,但在 WP8.1 中无效(有时滚动,有时不滚动)。 chatViewContent.UpdateLayout(); chatViewContent.ChangeView(null, chatViewContent.ScrollableHeight, null); 适用于 WP8.1 [未在 WinRT 中尝试,可能适用于两者]
      【解决方案5】:

      如果您使用 .NET 3.0 或更高版本,您可以使用ScrollViewer.ScrollToBottom()

      MSDN 文档:http://msdn.microsoft.com/en-us/library/system.windows.controls.scrollviewer.scrolltobottom(v=vs.110).aspx

      【讨论】:

        【解决方案6】:

        对于 WindowsPhone 通用应用,您可以使用:

         var scrollableHeight = ScrollViewer.ScrollableHeight;
                if (scrollableHeight > 0)
                {
                   ScrollViewer.ScrollToVerticalOffset(scrollableHeight);
                }
        

        【讨论】:

          【解决方案7】:

          我用过以下:

          ScrollViewer viewer = GetScrollViewer();
          if (viewer != null)
          {
              viewer.ScrollToVerticalOffset(viewer.ActualHeight);
          }
          

          另一种解决方案是将项目放入ListBox 并使用ScrollIntoView 方法

          【讨论】:

            【解决方案8】:

            ScrollViewer.ScrollToVerticalOffset(ScrollViewer.ActualHeight) 应该可以工作,但是如果您的代码刚刚更新了滚动查看器的内容,您可能需要在滚动之前调用 ScrollViewer.UpdateLayout(),这样 ScrollViewer.ActualHeight 就会启动迄今为止。

            【讨论】:

              【解决方案9】:

              对于 Windows Phone 8.0,您可以使用

              MyScrollViewer.ScrollToVerticalOffset(MyScrollViewer.ExtentHeight - MyScrollViewer.ViewportHeight);
              

              另请参考http://msdn.microsoft.com/en-us/library/windows/apps/system.windows.controls.scrollviewer.verticaloffset(v=vs.105).aspx

              【讨论】:

                猜你喜欢
                • 2015-09-30
                • 2017-09-15
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多