2012-06-23 11 views
13

En la actualidad, la única manera que he recibido mi código para desplazamiento automático para el final cuando agrego un nuevo artículo es la siguiente:mejor manera para desplazarse al final de 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> 

Código:

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

¿Es esta la forma aceptada de hacerlo? ¿Debo esperar algún período aleatorio?

+0

Hola, ¿encontró alguna solución mejor? – imslavko

+0

¿Esperaría 'a Dispatcher.Yield (DispatcherPriority.Input);' work? – springy76

Respuesta

0

He utilizado el siguiente:

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

Otra solución es poner los artículos en una ListBox y utilizar el método ScrollIntoView

0

ScrollViewer.ScrollToVerticalOffset (ScrollViewer.ActualHeight) debería funcionar, pero si su código acaba de actualizar el contenido del visor de desplazamiento, es posible que desee llamar a ScrollViewer.UpdateLayout() antes de desplazarse, de modo que ScrollViewer.ActualHeight estará actualizado.

2

ninguna asincronía aleatoria nunca es la respuesta a nada en ningún idioma, excepto tal vez JavaScript ... siempre tiene ese "olor a código" ¿sabes?

la forma correcta de hacer esto es para forzar un "refresh" de la medida de la ScrollViewer forma sincronizada para incluir a los niños recién añadidos llamando ScrollViewer.Measure(Size)

después de "volver a medir" la ScrollableHeight será el correcto valor y se puede usar como lo haría normalmente ..

así:

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

la Size estamos utilizando aquí es el RenderSize que técnicamente podría ser incorrecto en algunos casos de borde extremo, pero es bastante cercano a perfectamente ideal para nuestros propósitos. también podría usar técnicamente un Size arbitrariamente grande para el Measure(Size) y obtener el mismo efecto. lo que funcione mejor para su solución, espero que esta ayuda -CK

+0

'.Measure' funciona en WinRT, pero no funciona en WP8.1 (a veces se desplaza, a veces no funciona). 'chatViewContent.UpdateLayout(); chatViewContent.ChangeView (null, chatViewContent.ScrollableHeight, null); 'funciona en WP8.1 [no lo intenté en WinRT, puede funcionar en ambos] – Rui

15

Usando ActualHeight no funcionó para mí (todavía tengo que averiguar por qué) - pero utilizando ScrollableHeight como esto hizo el truco:

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

para Windows Phone 8.1 utilizo este:

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

Funciona bien en Windows 8.1 también –

+1

Esta es la forma correcta de hacerlo UWP aplicaciones. Si usa ScrollToVerticalOffset, el compilador le dará: 'ScrollViewer.ScrollToVerticalOffset (double)' está obsoleto: 'ScrollToVerticalOffset puede estar alterado o no disponible para versiones posteriores a Windows 8.1. En cambio, use ChangeView. ' –

2

Para WindowsPhone universal aplicación se puede utilizar:

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

En mi mejor opción opinión es heredar de ScrollViewer en forma siguiente:

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

y XAML

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

Luego puede utilizar directamente en XAML la nueva clase sin código adicional detrás de la cual es útil especialmente cuando tiene un código MVVM "puro".

Cuestiones relacionadas