Currently, the only way I have gotten my code to auto scroll to the end when I add a new item is the following:
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>
Code:
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);
Is this the accepted way of doing it? Do I have to wait for some random period of time?
Using ActualHeight did not work for me (I have yet to figure out why) - but using ScrollableHeight like this did the the trick:
I've used the following:
Another solution is to put the items into a
ListBox
and use the ScrollIntoView methodIn my opinion best option is to inherit from ScrollViewer in following way:
and XAML
Then you can use directly in XAML the new class without additional code behind which is usefull especailly when you have "pure" MVVM code.
ScrollViewer.ScrollToVerticalOffset(ScrollViewer.ActualHeight) should work, but if your code has just now updated the content of the scroll viewer, you may want to call ScrollViewer.UpdateLayout() before scrolling, so that ScrollViewer.ActualHeight will be up to date.
For WindowsPhone Universal app you can use:
no random asynchronicity is never the answer to anything in any language except maybe JavaScript... it just always has that "code smell" you know?
the proper way to do this is to force a "refresh" of the measure of the
ScrollViewer
synchronously to include the newly added children by callingScrollViewer.Measure(Size)
after you "re-measure" the
ScrollableHeight
will be the proper value and you can use it as you normally would..like this:
the
Size
we are using here is theRenderSize
which could technically be incorrect in some extreme edge cases, but it is pretty close to perfectly ideal for our purposes. you could also technically use an arbitrarily largeSize
for theMeasure(Size)
and get the same effect. whatever works best for your solution, hope this helps -ck