2012-06-23 9 views
13

В настоящее время единственный способ, который я получил мой код для автоматической прокрутки до конца, когда я добавить новый элемент заключается в следующем:Лучший способ Пролистайте до конца ScrollViewer

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

Является ли это принятым способом? Должен ли я ждать какой-то случайный период времени?

+0

Привет, вы нашли лучшее решение? – imslavko

+0

«Ожидает Dispatcher.Yield (DispatcherPriority.Input);' работает? – springy76

ответ

0

Я использовал следующие:

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

Другим решением является помещаете элементы в ListBox и использовать ScrollIntoView метод

0

ScrollViewer.ScrollToVerticalOffset (ScrollViewer.ActualHeight) должен работать, но если ваш код только что обновил содержимое средства просмотра прокрутки, вы можете вызвать ScrollViewer.UpdateLayout() перед прокруткой, чтобы ScrollViewer.ActualHeight был обновлен.

2

Никакая случайная асинхронность никогда не является ответом на что-либо на любом языке, кроме, может быть, JavaScript ... у него всегда есть этот «запах кода», который вы знаете?

правильный способ сделать это, чтобы заставить «обновить» в меру ScrollViewer синхронно включить вновь добавляемые детей по телефону ScrollViewer.Measure(Size)

после того, как вы «повторно измерения» 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); 
    } 

Size мы используем здесь является RenderSize whic h может быть технически неверным в некоторых случаях с экстремальными краями, но это довольно близко к идеально идеально подходит для наших целей. вы также можете технически использовать произвольно большой Size для Measure(Size) и получить тот же эффект. что лучше работает для вашего решения, надеюсь, что это помогает -ck

+0

'.Measure' работает в WinRT, однако он не работает в WP8.1 (иногда он прокручивается, иногда это не так). 'ChatViewContent.UpdateLayout(); chatViewContent.ChangeView (null, chatViewContent.ScrollableHeight, null); 'работает в WP8.1 [не пробовал в WinRT, может работать в обоих) – Rui

15

Использование ActualHeight не работает для меня (я до сих пор понять, почему) - но с использованием ScrollableHeight, как это сделал трюк:

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

Для Windows Phone 8.1 Я использую это:

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

Хорошо работает и в Windows 8.1 –

+1

Это правильный способ сделать это для UWP-приложения. Если вы используете ScrollToVerticalOffset, компилятор даст вам: «ScrollViewer.ScrollToVerticalOffset (double)» устарел: «ScrollToVerticalOffset может быть изменен или недоступен для релизов после Windows 8.1. Вместо этого используйте ChangeView. ' –

2

Для WindowsPhone Универсальное приложение вы можете использовать:

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

По моему мнению, самым лучшим вариантом является наследование от 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.