Лучший способ прокрутки до конца 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);
Это приемлемый способ сделать это? Должен ли я ждать какой-то случайный период времени?
Ответы
Ответ 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);
Ответ 3
никакая случайная асинхронность никогда не является ответом на что-либо на любом языке, кроме, может быть, 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);
}
the Size
, который мы используем здесь, это RenderSize
, который может быть технически некорректным в некоторых случаях экстремальных краев, но он близок к идеально идеальному для наших целей. вы также можете технически использовать сколь угодно большой Size
для Measure(Size)
и получить тот же эффект. что лучше всего подходит для вашего решения, надеюсь, что это поможет -ck
Ответ 4
Для универсального приложения WindowsPhone вы можете использовать:
var scrollableHeight = ScrollViewer.ScrollableHeight;
if (scrollableHeight > 0)
{
ScrollViewer.ScrollToVerticalOffset(scrollableHeight);
}
Ответ 5
На мой взгляд, лучший вариант - наследовать от 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.
Ответ 6
Если вы работаете с .NET 3.0 или более поздней версией, вы можете использовать ScrollViewer.ScrollToBottom()
.
MSDN doc: http://msdn.microsoft.com/en-us/library/system.windows.controls.scrollviewer.scrolltobottom(v=vs.110).aspx
Ответ 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