Reputation: 4408
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?
Upvotes: 14
Views: 18933
Reputation: 505
In my opinion best option is to inherit from ScrollViewer in following way:
public partial class AutoScrollViewer
{
public AutoScrollViewer()
{
InitializeComponent();
this.SizeChanged += (sender, args) => this.ScrollToBottom();
}
}
and XAML
<ScrollViewer x:Class="AutoScrollViewer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</ScrollViewer>
Then you can use directly in XAML the new class without additional code behind which is usefull especailly when you have "pure" MVVM code.
Upvotes: 3
Reputation: 677
For WindowsPhone Universal app you can use:
var scrollableHeight = ScrollViewer.ScrollableHeight;
if (scrollableHeight > 0)
{
ScrollViewer.ScrollToVerticalOffset(scrollableHeight);
}
Upvotes: 2
Reputation: 504
For Windows Phone 8.0, you can use
MyScrollViewer.ScrollToVerticalOffset(MyScrollViewer.ExtentHeight - MyScrollViewer.ViewportHeight);
Please also refer to http://msdn.microsoft.com/en-us/library/windows/apps/system.windows.controls.scrollviewer.verticaloffset(v=vs.105).aspx
Upvotes: 0
Reputation: 602
If you are working with .NET 3.0 or later, you can use ScrollViewer.ScrollToBottom()
.
Upvotes: 2
Reputation: 3001
For Windows Phone 8.1 I use this:
MyScrollViewer.ChangeView(0.0f, double.MaxValue, 1.0f);
Upvotes: 15
Reputation: 1212
Using ActualHeight did not work for me (I have yet to figure out why) - but using ScrollableHeight like this did the the trick:
// adding item to ItemsControl...
// ...
_scrollViewer.UpdateLayout();
_scrollViewer.ScrollToVerticalOffset(_scrollViewer.ScrollableHeight);
Upvotes: 16
Reputation: 6761
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 calling ScrollViewer.Measure(Size)
after you "re-measure" the ScrollableHeight
will be the proper value and you can use it as you normally would..
like this:
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);
}
the Size
we are using here is the RenderSize
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 large Size
for the Measure(Size)
and get the same effect. whatever works best for your solution, hope this helps -ck
Upvotes: 2
Reputation: 560
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.
Upvotes: 0
Reputation: 12465
I've used the following:
ScrollViewer viewer = GetScrollViewer();
if (viewer != null)
{
viewer.ScrollToVerticalOffset(viewer.ActualHeight);
}
Another solution is to put the items into a ListBox
and use the ScrollIntoView method
Upvotes: 0